From 037e72d614b8b3a9120d3e6a232281ac857f657f Mon Sep 17 00:00:00 2001 From: Andrea De Rinaldis Date: Mon, 18 Sep 2023 22:29:05 +0200 Subject: [PATCH 1/7] fix: refactored ID generation using MD5 algorithm --- .github/workflows/update_code.yml | 38 -------- scripts/scripts.sql | 95 ------------------- .../mocker/entity/MockResourceEntity.java | 3 - .../repository/MockResourceRepository.java | 2 +- .../pagopa/mocker/service/MockerService.java | 2 +- .../it/gov/pagopa/mocker/util/Constants.java | 2 + .../it/gov/pagopa/mocker/util/Utility.java | 15 ++- src/main/resources/h2/data-h2.sql | 20 +--- src/main/resources/h2/schema-h2.sql | 23 ----- .../mocker/service/MockerServiceTest.java | 27 +++--- .../gov/pagopa/mocker/util/UtilityTest.java | 8 +- .../mock_resources/mock_resource_ok.json | 3 +- .../mock_resource_ok_notinjection.json | 3 +- .../mock_resource_ok_plainstring.json | 3 +- .../mock_resource_ok_urlcheck.json | 3 +- .../mock_resource_onlymainrule.json | 3 +- .../mock_resources/mock_resource_xml_ok.json | 3 +- 17 files changed, 46 insertions(+), 207 deletions(-) delete mode 100644 .github/workflows/update_code.yml delete mode 100644 scripts/scripts.sql diff --git a/.github/workflows/update_code.yml b/.github/workflows/update_code.yml deleted file mode 100644 index e254b35..0000000 --- a/.github/workflows/update_code.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: Update Code - -on: - issue_comment: - types: [created, edited] - - -permissions: - contents: write - pull-requests: write - issues: write - -jobs: - update: - name: Update Openapi and Formatting - runs-on: ubuntu-latest - if: ${{ contains(github.event.comment.body, 'update_code') }} - steps: - - name: Checkout - uses: actions/checkout@v3 - with: - token: ${{ secrets.BOT_TOKEN_GITHUB }} - - - name: Checkout Pull Request - run: hub pr checkout ${{ github.event.issue.number }} - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Set up JDK 11 - uses: actions/setup-java@v1 - with: - java-version: 11 - - - name: Run Service on Docker - shell: bash - run: | - cd ./docker - chmod +x ./run_docker.sh - ./run_docker.sh local diff --git a/scripts/scripts.sql b/scripts/scripts.sql deleted file mode 100644 index 5ef8eb6..0000000 --- a/scripts/scripts.sql +++ /dev/null @@ -1,95 +0,0 @@ - -CREATE SCHEMA mocker; - -CREATE TABLE mocker.mock_resource ( - id varchar NOT NULL, - resource_id varchar NOT NULL, - subsystem_url varchar NOT NULL, - resource_url varchar NOT NULL, - http_method varchar NOT NULL, - "name" varchar NOT NULL, - is_active boolean NOT NULL, - CONSTRAINT mock_resource_pk PRIMARY KEY (id) -); - -CREATE UNIQUE INDEX mock_resource_idx ON mocker.mock_resource(resource_id); - -CREATE TABLE mocker.mock_response ( - id varchar NOT NULL, - body varchar NULL, - status int8 NOT NULL, - CONSTRAINT mock_response_pk PRIMARY KEY (id) -); - -CREATE TABLE mocker.mock_rule ( - id varchar NOT NULL, - "name" varchar NOT NULL, - "order" int8 NOT NULL, - is_active boolean NOT NULL, - resource_id varchar NOT NULL, - response_id varchar NOT NULL, - CONSTRAINT mock_rule_pk PRIMARY KEY (id), - CONSTRAINT mock_rule_mock_resource_fk FOREIGN KEY (resource_id) REFERENCES mocker.mock_resource(id) ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT mock_rule_mock_response_fk FOREIGN KEY (response_id) REFERENCES mocker.mock_response(id) ON DELETE CASCADE ON UPDATE CASCADE -); - -CREATE TABLE mocker.mock_condition ( - id varchar NOT NULL, - "order" int8 NOT NULL, - field_position varchar NOT NULL, - content_type varchar NOT NULL, - field_name varchar NOT NULL, - condition_type varchar NOT NULL, - condition_value varchar NULL, - rule_id varchar NOT NULL, - CONSTRAINT mock_condition_pk PRIMARY KEY (id), - CONSTRAINT mock_condition_fk FOREIGN KEY (rule_id) REFERENCES mocker.mock_rule(id) ON DELETE CASCADE ON UPDATE CASCADE -); - -CREATE TABLE mocker.response_header ( - response_id varchar NOT NULL, - "header" varchar NOT NULL, - "value" varchar NOT NULL, - CONSTRAINT response_header_pk PRIMARY KEY (response_id,"header"), - CONSTRAINT response_header_fk FOREIGN KEY (response_id) REFERENCES mocker.mock_response(id) ON DELETE CASCADE ON UPDATE CASCADE -); - -CREATE TABLE mocker.injectable_parameter ( - response_id varchar NOT NULL, - "parameter" varchar NOT NULL, - CONSTRAINT injectable_parameter_pk PRIMARY KEY (response_id,"parameter"), - CONSTRAINT injectable_parameter_fk FOREIGN KEY (response_id) REFERENCES mocker.mock_response(id) ON DELETE CASCADE ON UPDATE CASCADE -); - -CREATE TABLE mocker.tag ( - id varchar NOT NULL, - "value" varchar NOT NULL, - CONSTRAINT tag_pk PRIMARY KEY (id) -); - -CREATE TABLE mocker.mock_resource_tag ( - mock_resource_id varchar NOT NULL, - tag_id varchar NOT NULL, - CONSTRAINT mock_resource_tag_pk PRIMARY KEY (mock_resource_id,tag_id), - CONSTRAINT mock_resource_tag_mock_resource_fk FOREIGN KEY (mock_resource_id) REFERENCES mocker.mock_resource(id) ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT mock_resource_tag_tag_fk FOREIGN KEY (tag_id) REFERENCES mocker.tag(id) ON DELETE CASCADE ON UPDATE CASCADE -); - -CREATE TABLE mocker.mock_rule_tag ( - mock_rule_id varchar NOT NULL, - tag_id varchar NOT NULL, - CONSTRAINT mock_rule_tag_pk PRIMARY KEY (mock_rule_id,tag_id), - CONSTRAINT mock_rule_tag_mock_rule_fk FOREIGN KEY (mock_rule_id) REFERENCES mocker.mock_rule(id) ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT mock_rule_tag_tag_fk FOREIGN KEY (tag_id) REFERENCES mocker.tag(id) ON DELETE CASCADE ON UPDATE CASCADE -); - - -CREATE USER mocker_user PASSWORD ''; -GRANT CONNECT ON DATABASE mocker TO mocker_user; -GRANT USAGE ON SCHEMA mocker TO mocker_user; -grant select on all tables in schema mocker to mocker_user; -grant select on all sequences in schema mocker to mocker_user; -grant execute on all functions in schema mocker to mocker_user; -grant all on all tables in schema mocker to mocker_user; -grant all on all sequences in schema mocker to mocker_user; -grant all on all functions in schema mocker to mocker_user; \ No newline at end of file diff --git a/src/main/java/it/gov/pagopa/mocker/entity/MockResourceEntity.java b/src/main/java/it/gov/pagopa/mocker/entity/MockResourceEntity.java index c9905de..ed3623a 100644 --- a/src/main/java/it/gov/pagopa/mocker/entity/MockResourceEntity.java +++ b/src/main/java/it/gov/pagopa/mocker/entity/MockResourceEntity.java @@ -23,9 +23,6 @@ public class MockResourceEntity implements Serializable { @Column(name = "id") private String id; - @Column(name = "resource_id") - private String resourceId; - @Column(name = "subsystem_url") private String subsystemUrl; diff --git a/src/main/java/it/gov/pagopa/mocker/repository/MockResourceRepository.java b/src/main/java/it/gov/pagopa/mocker/repository/MockResourceRepository.java index 8a6b24f..4b6f260 100644 --- a/src/main/java/it/gov/pagopa/mocker/repository/MockResourceRepository.java +++ b/src/main/java/it/gov/pagopa/mocker/repository/MockResourceRepository.java @@ -9,6 +9,6 @@ public interface MockResourceRepository extends Repository { @Transactional - Optional findByResourceId(String resourceId); + Optional findById(String id); } diff --git a/src/main/java/it/gov/pagopa/mocker/service/MockerService.java b/src/main/java/it/gov/pagopa/mocker/service/MockerService.java index a5dbc4a..a30c786 100644 --- a/src/main/java/it/gov/pagopa/mocker/service/MockerService.java +++ b/src/main/java/it/gov/pagopa/mocker/service/MockerService.java @@ -44,7 +44,7 @@ public ExtractedResponse analyze(ExtractedRequest requestData) { } private MockResourceEntity getMockResourceFromDB(ExtractedRequest requestData) throws MockerNotRegisteredException, MockerNotActiveException { - MockResourceEntity mockResource = dao.findByResourceId(requestData.getId()).orElseThrow(() -> new MockerNotRegisteredException(requestData.getUrl())); + MockResourceEntity mockResource = dao.findById(requestData.getId()).orElseThrow(() -> new MockerNotRegisteredException(requestData.getUrl())); if (Boolean.FALSE.equals(mockResource.getIsActive())) { throw new MockerNotActiveException(requestData.getUrl()); } diff --git a/src/main/java/it/gov/pagopa/mocker/util/Constants.java b/src/main/java/it/gov/pagopa/mocker/util/Constants.java index ba21477..1915d21 100644 --- a/src/main/java/it/gov/pagopa/mocker/util/Constants.java +++ b/src/main/java/it/gov/pagopa/mocker/util/Constants.java @@ -26,6 +26,8 @@ public class Constants { public static final String EMPTY_STRING = ""; + public static final String WHITESPACE = " "; + private Constants() {} } diff --git a/src/main/java/it/gov/pagopa/mocker/util/Utility.java b/src/main/java/it/gov/pagopa/mocker/util/Utility.java index bfc3c79..eb7d428 100644 --- a/src/main/java/it/gov/pagopa/mocker/util/Utility.java +++ b/src/main/java/it/gov/pagopa/mocker/util/Utility.java @@ -1,14 +1,27 @@ package it.gov.pagopa.mocker.util; +import lombok.extern.slf4j.Slf4j; + import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.util.*; +@Slf4j public class Utility { private Utility() {} public static String generateID(String url, String httpMethod) { - return httpMethod.concat(url).replaceAll("[\\\\/\\-_]+", Constants.EMPTY_STRING).toLowerCase(); + String hashedId = ""; + try { + byte[] requestIdBytes = httpMethod.concat(Constants.WHITESPACE).concat(url).getBytes(StandardCharsets.UTF_8); + MessageDigest md = MessageDigest.getInstance("MD5"); + hashedId = new String(md.digest(requestIdBytes)); + } catch (NoSuchAlgorithmException e) { + log.error("Error while generating the hash value from URL and HTTP method. No valid algorithm found as 'MD5'.", e); + } + return hashedId; } public static boolean isNullOrEmpty(String content) { diff --git a/src/main/resources/h2/data-h2.sql b/src/main/resources/h2/data-h2.sql index e490b11..e60ef00 100644 --- a/src/main/resources/h2/data-h2.sql +++ b/src/main/resources/h2/data-h2.sql @@ -5,8 +5,8 @@ INSERT INTO mocker.tag(id, "value") VALUES('88513e6d-7229-43ea-96b5-f83ffd96d5f5 -INSERT INTO mocker.mock_resource(id, resource_id, subsystem_url, resource_url, http_method, "name", is_active) -VALUES('70aa0abb-0001-0212-aa01-2cb1a0f00301', 'gpdreportingorgsenrollmentapiv1organizations77777777777get', 'gpd-reporting-orgs-enrollment/api/v1', 'organizations/77777777777', 'GET', 'Get enrolled organization with ID 77777777777', true); +INSERT INTO mocker.mock_resource(id, subsystem_url, resource_url, http_method, "name", is_active) +VALUES('c7b8221105a531da9a731f334d176984', 'gpd-reporting-orgs-enrollment/api/v1', 'organizations/77777777777', 'GET', 'Get enrolled organization with ID 77777777777', true); @@ -21,23 +21,9 @@ VALUES('26e05a1f-9621-4e24-a57d-28694ff30306', 'Content-Type', 'application/json INSERT INTO mocker.mock_rule(id, "name", "order", is_active, resource_id, response_id) -VALUES('6c08a21c-6a92-4f6b-a1e1-bf68c4e099c9', 'Main rule', 1, true, '70aa0abb-0001-0212-aa01-2cb1a0f00301', '26e05a1f-9621-4e24-a57d-28694ff30306'); +VALUES('6c08a21c-6a92-4f6b-a1e1-bf68c4e099c9', 'Main rule', 1, true, 'c7b8221105a531da9a731f334d176984', '26e05a1f-9621-4e24-a57d-28694ff30306'); INSERT INTO mocker.mock_condition(id, "order", field_position, content_type, field_name, condition_type, condition_value, rule_id) VALUES('6b0b003d-74f4-428e-b950-61f42e02bf07', 1, 'HEADER', 'STRING', 'ClientId', 'NULL', '', '6c08a21c-6a92-4f6b-a1e1-bf68c4e099c9'); - - - -INSERT INTO mocker.mock_resource_tag(mock_resource_id, tag_id) -VALUES('70aa0abb-0001-0212-aa01-2cb1a0f00301', '398ddf77-8012-4767-84aa-87ad194d3ac9'); -INSERT INTO mocker.mock_resource_tag(mock_resource_id, tag_id) -VALUES('70aa0abb-0001-0212-aa01-2cb1a0f00301', '261af795-2652-401e-a9c2-dcc160041bf6'); -INSERT INTO mocker.mock_resource_tag(mock_resource_id, tag_id) -VALUES('70aa0abb-0001-0212-aa01-2cb1a0f00301', 'eaa80a30-2992-47fc-b607-4a248d03066b'); - - - -INSERT INTO mocker.mock_rule_tag(mock_rule_id, tag_id) -VALUES('6c08a21c-6a92-4f6b-a1e1-bf68c4e099c9', '88513e6d-7229-43ea-96b5-f83ffd96d5f5'); diff --git a/src/main/resources/h2/schema-h2.sql b/src/main/resources/h2/schema-h2.sql index 89294da..c865296 100644 --- a/src/main/resources/h2/schema-h2.sql +++ b/src/main/resources/h2/schema-h2.sql @@ -1,6 +1,5 @@ CREATE TABLE mocker.mock_resource ( id varchar NOT NULL, - resource_id varchar NOT NULL, subsystem_url varchar NOT NULL, resource_url varchar NOT NULL, http_method varchar NOT NULL, @@ -54,26 +53,4 @@ CREATE TABLE mocker.injectable_parameter ( "parameter" varchar NOT NULL, CONSTRAINT injectable_parameter_pk PRIMARY KEY (response_id,"parameter"), CONSTRAINT injectable_parameter_fk FOREIGN KEY (response_id) REFERENCES mocker.mock_response(id) ON DELETE CASCADE ON UPDATE CASCADE -); - -CREATE TABLE mocker.tag ( - id varchar NOT NULL, - "value" varchar NOT NULL, - CONSTRAINT tag_pk PRIMARY KEY (id) -); - -CREATE TABLE mocker.mock_resource_tag ( - mock_resource_id varchar NOT NULL, - tag_id varchar NOT NULL, - CONSTRAINT mock_resource_tag_pk PRIMARY KEY (mock_resource_id,tag_id), - CONSTRAINT mock_resource_tag_mock_resource_fk FOREIGN KEY (mock_resource_id) REFERENCES mocker.mock_resource(id) ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT mock_resource_tag_tag_fk FOREIGN KEY (tag_id) REFERENCES mocker.tag(id) ON DELETE CASCADE ON UPDATE CASCADE -); - -CREATE TABLE mocker.mock_rule_tag ( - mock_rule_id varchar NOT NULL, - tag_id varchar NOT NULL, - CONSTRAINT mock_rule_tag_pk PRIMARY KEY (mock_rule_id,tag_id), - CONSTRAINT mock_rule_tag_mock_rule_fk FOREIGN KEY (mock_rule_id) REFERENCES mocker.mock_rule(id) ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT mock_rule_tag_tag_fk FOREIGN KEY (tag_id) REFERENCES mocker.tag(id) ON DELETE CASCADE ON UPDATE CASCADE ); \ No newline at end of file diff --git a/src/test/java/it/gov/pagopa/mocker/service/MockerServiceTest.java b/src/test/java/it/gov/pagopa/mocker/service/MockerServiceTest.java index 187a1fc..6ffe212 100644 --- a/src/test/java/it/gov/pagopa/mocker/service/MockerServiceTest.java +++ b/src/test/java/it/gov/pagopa/mocker/service/MockerServiceTest.java @@ -18,7 +18,6 @@ import org.skyscreamer.jsonassert.JSONCompareMode; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.dao.DataAccessException; import org.springframework.dao.DataRetrievalFailureException; import org.springframework.mock.web.MockHttpServletRequest; @@ -59,7 +58,7 @@ void testOK_mainRule() { // Mocking responses MockResourceEntity mockResource = new Gson().fromJson(TestUtil.readJsonFromFile("request/mock_resources/mock_resource_ok.json"), MockResourceEntity.class); - when(repository.findByResourceId(anyString())).thenReturn(Optional.ofNullable(mockResource)); + when(repository.findById(anyString())).thenReturn(Optional.ofNullable(mockResource)); // Executing logic ExtractedResponse response = service.analyze(extractedRequest); @@ -85,7 +84,7 @@ void testOK_parachuteRule() { // Mocking responses MockResourceEntity mockResource = new Gson().fromJson(TestUtil.readJsonFromFile("request/mock_resources/mock_resource_ok.json"), MockResourceEntity.class); - when(repository.findByResourceId(anyString())).thenReturn(Optional.ofNullable(mockResource)); + when(repository.findById(anyString())).thenReturn(Optional.ofNullable(mockResource)); // Executing logic ExtractedResponse response = service.analyze(extractedRequest); @@ -111,7 +110,7 @@ void testOK_notInjectedParam() { // Mocking responses MockResourceEntity mockResource = new Gson().fromJson(TestUtil.readJsonFromFile("request/mock_resources/mock_resource_ok_notinjection.json"), MockResourceEntity.class); - when(repository.findByResourceId(anyString())).thenReturn(Optional.ofNullable(mockResource)); + when(repository.findById(anyString())).thenReturn(Optional.ofNullable(mockResource)); // Executing logic ExtractedResponse response = service.analyze(extractedRequest); @@ -137,7 +136,7 @@ void testOK_noRule() { // Mocking responses MockResourceEntity mockResource = new Gson().fromJson(TestUtil.readJsonFromFile("request/mock_resources/mock_resource_onlymainrule.json"), MockResourceEntity.class); - when(repository.findByResourceId(anyString())).thenReturn(Optional.ofNullable(mockResource)); + when(repository.findById(anyString())).thenReturn(Optional.ofNullable(mockResource)); // Executing logic ExtractedResponse response = service.analyze(extractedRequest); @@ -162,7 +161,7 @@ void testOK_ruleForURLCondition() { // Mocking responses MockResourceEntity mockResource = new Gson().fromJson(TestUtil.readJsonFromFile("request/mock_resources/mock_resource_ok_urlcheck.json"), MockResourceEntity.class); - when(repository.findByResourceId(anyString())).thenReturn(Optional.ofNullable(mockResource)); + when(repository.findById(anyString())).thenReturn(Optional.ofNullable(mockResource)); // Executing logic ExtractedResponse response = service.analyze(extractedRequest); @@ -188,7 +187,7 @@ void testOK_otherContentType() { // Mocking responses MockResourceEntity mockResource = new Gson().fromJson(TestUtil.readJsonFromFile("request/mock_resources/mock_resource_ok_plainstring.json"), MockResourceEntity.class); - when(repository.findByResourceId(anyString())).thenReturn(Optional.ofNullable(mockResource)); + when(repository.findById(anyString())).thenReturn(Optional.ofNullable(mockResource)); // Executing logic ExtractedResponse response = service.analyze(extractedRequest); @@ -214,7 +213,7 @@ void testOK_xmlRequest() { // Mocking responses MockResourceEntity mockResource = new Gson().fromJson(TestUtil.readJsonFromFile("request/mock_resources/mock_resource_xml_ok.json"), MockResourceEntity.class); - when(repository.findByResourceId(anyString())).thenReturn(Optional.ofNullable(mockResource)); + when(repository.findById(anyString())).thenReturn(Optional.ofNullable(mockResource)); // Executing logic ExtractedResponse response = service.analyze(extractedRequest); @@ -240,7 +239,7 @@ void testOK_nullBodyForNonNullCondition() { // Mocking responses MockResourceEntity mockResource = new Gson().fromJson(TestUtil.readJsonFromFile("request/mock_resources/mock_resource_ok.json"), MockResourceEntity.class); - when(repository.findByResourceId(anyString())).thenReturn(Optional.ofNullable(mockResource)); + when(repository.findById(anyString())).thenReturn(Optional.ofNullable(mockResource)); // Executing logic ExtractedResponse response = service.analyze(extractedRequest); @@ -265,7 +264,7 @@ void testKO_unparseableXml() { // Mocking responses MockResourceEntity mockResource = new Gson().fromJson(TestUtil.readJsonFromFile("request/mock_resources/mock_resource_xml_ok.json"), MockResourceEntity.class); - when(repository.findByResourceId(anyString())).thenReturn(Optional.ofNullable(mockResource)); + when(repository.findById(anyString())).thenReturn(Optional.ofNullable(mockResource)); // Executing logic ExtractedResponse response = service.analyze(extractedRequest); @@ -289,7 +288,7 @@ void testKO_noResourceRegistered() { String extractedResponseBody = "{ \"message\": \"No valid mock resource is registered at URL [ec-service/api/v1/organizations/77777777777].\" }"; // Mocking responses - when(repository.findByResourceId(anyString())).thenReturn(Optional.empty()); + when(repository.findById(anyString())).thenReturn(Optional.empty()); // Executing logic ExtractedResponse response = service.analyze(extractedRequest); @@ -315,7 +314,7 @@ void testKO_inactiveResource() { // Mocking responses MockResourceEntity mockResource = new Gson().fromJson(TestUtil.readJsonFromFile("request/mock_resources/mock_resource_onlymainrule.json"), MockResourceEntity.class); mockResource.setIsActive(false); - when(repository.findByResourceId(anyString())).thenReturn(Optional.ofNullable(mockResource)); + when(repository.findById(anyString())).thenReturn(Optional.ofNullable(mockResource)); // Executing logic ExtractedResponse response = service.analyze(extractedRequest); @@ -338,7 +337,7 @@ void testKO_genericExceptionJSON() { String extractedResponseBody = "{ \"message\": \"An unexpected error occurred while searching for mocked resource.\" }"; // Mocking responses - when(repository.findByResourceId(anyString())).thenThrow(new DataRetrievalFailureException("some description")); + when(repository.findById(anyString())).thenThrow(new DataRetrievalFailureException("some description")); // Executing logic ExtractedResponse response = service.analyze(extractedRequest); @@ -361,7 +360,7 @@ void testKO_genericExceptionXML() { String extractedResponseBody = "KOAn unexpected error occurred while searching for mocked resource."; // Mocking responses - when(repository.findByResourceId(anyString())).thenThrow(new DataRetrievalFailureException("some description")); + when(repository.findById(anyString())).thenThrow(new DataRetrievalFailureException("some description")); // Executing logic ExtractedResponse response = service.analyze(extractedRequest); diff --git a/src/test/java/it/gov/pagopa/mocker/util/UtilityTest.java b/src/test/java/it/gov/pagopa/mocker/util/UtilityTest.java index 506bd8a..c3583f3 100644 --- a/src/test/java/it/gov/pagopa/mocker/util/UtilityTest.java +++ b/src/test/java/it/gov/pagopa/mocker/util/UtilityTest.java @@ -5,6 +5,9 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; + import static org.junit.jupiter.api.Assertions.*; @SpringBootTest(classes = MockerApplication.class) @@ -15,8 +18,9 @@ class UtilityTest { void testGenerateID() { String url = "/Creditor-Institutions/7777\\7777777/some__detail"; String httpMethod = "GET"; - String result = Utility.generateID(url, httpMethod); - assertEquals("getcreditorinstitutions77777777777somedetail", result); + byte[] requestIdBytes = httpMethod.concat(Constants.WHITESPACE).concat(url).getBytes(StandardCharsets.UTF_8); + MessageDigest md = MessageDigest.getInstance("MD5"); + assertEquals(new String(md.digest(requestIdBytes)), Utility.generateID(url, httpMethod)); } @Test diff --git a/src/test/resources/request/mock_resources/mock_resource_ok.json b/src/test/resources/request/mock_resources/mock_resource_ok.json index ebd6226..0910655 100644 --- a/src/test/resources/request/mock_resources/mock_resource_ok.json +++ b/src/test/resources/request/mock_resources/mock_resource_ok.json @@ -1,6 +1,5 @@ { - "id": "mock-resource-uuid", - "resourceId": "postecserviceapiv1organizations77777777777", + "id": "bce9086e9cf15dd62401b7a440f75610", "name": "Get creditor institution with ID 77777777777", "subsystemUrl": "ec-service/api/v1", "resourceUrl": "organizations/77777777777", diff --git a/src/test/resources/request/mock_resources/mock_resource_ok_notinjection.json b/src/test/resources/request/mock_resources/mock_resource_ok_notinjection.json index 6d6fe21..05dc448 100644 --- a/src/test/resources/request/mock_resources/mock_resource_ok_notinjection.json +++ b/src/test/resources/request/mock_resources/mock_resource_ok_notinjection.json @@ -1,6 +1,5 @@ { - "id": "mock-resource-uuid", - "resourceId": "postecserviceapiv1organizations77777777777", + "id": "bce9086e9cf15dd62401b7a440f75610", "name": "Get creditor institution with ID 77777777777", "subsystemUrl": "ec-service/api/v1", "resourceUrl": "organizations/77777777777", diff --git a/src/test/resources/request/mock_resources/mock_resource_ok_plainstring.json b/src/test/resources/request/mock_resources/mock_resource_ok_plainstring.json index 3bfc678..c6691b3 100644 --- a/src/test/resources/request/mock_resources/mock_resource_ok_plainstring.json +++ b/src/test/resources/request/mock_resources/mock_resource_ok_plainstring.json @@ -1,6 +1,5 @@ { - "id": "mock-resource-uuid", - "resourceId": "postecserviceapiv1organizations77777777777", + "id": "bce9086e9cf15dd62401b7a440f75610", "name": "Get creditor institution with ID 77777777777", "subsystemUrl": "ec-service/api/v1", "resourceUrl": "organizations/77777777777", diff --git a/src/test/resources/request/mock_resources/mock_resource_ok_urlcheck.json b/src/test/resources/request/mock_resources/mock_resource_ok_urlcheck.json index 94e0272..c80df86 100644 --- a/src/test/resources/request/mock_resources/mock_resource_ok_urlcheck.json +++ b/src/test/resources/request/mock_resources/mock_resource_ok_urlcheck.json @@ -1,6 +1,5 @@ { - "id": "mock-resource-uuid", - "resourceId": "postecserviceapiv1organizations77777777777", + "id": "bce9086e9cf15dd62401b7a440f75610", "name": "Get creditor institution with ID 77777777777", "subsystemUrl": "ec-service/api/v1", "resourceUrl": "organizations/77777777777", diff --git a/src/test/resources/request/mock_resources/mock_resource_onlymainrule.json b/src/test/resources/request/mock_resources/mock_resource_onlymainrule.json index c16cd63..aed1549 100644 --- a/src/test/resources/request/mock_resources/mock_resource_onlymainrule.json +++ b/src/test/resources/request/mock_resources/mock_resource_onlymainrule.json @@ -1,6 +1,5 @@ { - "id": "mock-resource-uuid", - "resourceId": "postecserviceapiv1organizations77777777777", + "id": "bce9086e9cf15dd62401b7a440f75610", "name": "Get creditor institution with ID 77777777777", "subsystemUrl": "ec-service/api/v1", "resourceUrl": "organizations/77777777777", diff --git a/src/test/resources/request/mock_resources/mock_resource_xml_ok.json b/src/test/resources/request/mock_resources/mock_resource_xml_ok.json index 1237460..cda1cfb 100644 --- a/src/test/resources/request/mock_resources/mock_resource_xml_ok.json +++ b/src/test/resources/request/mock_resources/mock_resource_xml_ok.json @@ -1,6 +1,5 @@ { - "id": "mock-resource-uuid", - "resourceId": "postecserviceapiv1organizations77777777777", + "id": "bce9086e9cf15dd62401b7a440f75610", "name": "Get creditor institution with ID 77777777777 [XML]", "subsystemUrl": "ec-service/api/v1", "resourceUrl": "organizations/77777777777", From f6607a91b4b7c7c169543ce0c9b0fc59cb70deac Mon Sep 17 00:00:00 2001 From: Andrea De Rinaldis Date: Wed, 4 Oct 2023 23:18:01 +0200 Subject: [PATCH 2/7] breaking: major refactoring of the code --- pom.xml | 4 ++ .../gov/pagopa/mocker/config/RedisConf.java | 55 ++++++++++++++++ .../{controller => config}/WebConf.java | 3 +- .../mocker/controller/ProxyServlet.java | 9 +-- .../pagopa/mocker/model/ExtractedRequest.java | 7 ++- .../mocker/model/ExtractedResponse.java | 1 + .../pagopa/mocker/service/CacheService.java | 28 +++++++++ .../pagopa/mocker/service/ProxyService.java | 62 +++++++++++++++++++ .../service/validator/ResourceExtractor.java | 1 + .../service/validator/ResponseBuilder.java | 6 +- .../it/gov/pagopa/mocker/util/Constants.java | 10 +++ .../mocker/util/ObjectRedisSerializer.java | 38 ++++++++++++ .../it/gov/pagopa/mocker/util/Utility.java | 20 ++++-- src/main/resources/application-h2.properties | 6 +- .../resources/application-local.properties | 9 ++- src/main/resources/application.properties | 6 +- .../gov/pagopa/mocker/util/UtilityTest.java | 2 +- 17 files changed, 248 insertions(+), 19 deletions(-) create mode 100644 src/main/java/it/gov/pagopa/mocker/config/RedisConf.java rename src/main/java/it/gov/pagopa/mocker/{controller => config}/WebConf.java (89%) create mode 100644 src/main/java/it/gov/pagopa/mocker/service/CacheService.java create mode 100644 src/main/java/it/gov/pagopa/mocker/service/ProxyService.java create mode 100644 src/main/java/it/gov/pagopa/mocker/util/ObjectRedisSerializer.java diff --git a/pom.xml b/pom.xml index 5531ab4..2fb73ad 100644 --- a/pom.xml +++ b/pom.xml @@ -27,6 +27,10 @@ org.springframework.boot spring-boot-starter-data-jpa + + org.springframework.boot + spring-boot-starter-data-redis + org.postgresql postgresql diff --git a/src/main/java/it/gov/pagopa/mocker/config/RedisConf.java b/src/main/java/it/gov/pagopa/mocker/config/RedisConf.java new file mode 100644 index 0000000..990eb79 --- /dev/null +++ b/src/main/java/it/gov/pagopa/mocker/config/RedisConf.java @@ -0,0 +1,55 @@ +package it.gov.pagopa.mocker.config; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import it.gov.pagopa.mocker.model.ExtractedRequest; +import it.gov.pagopa.mocker.util.ObjectRedisSerializer; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisStandaloneConfiguration; +import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +@Configuration +public class RedisConf { + + @Value("${redis.host}") + private String redisHost; + + @Value("${redis.port}") + private int redisPort; + + @Value("${redis.pwd}") + private String redisPwd; + + @Bean + public ObjectMapper objectMapper() { + final var objectMapper = new ObjectMapper().findAndRegisterModules(); + objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + return objectMapper; + } + + @Bean + public LettuceConnectionFactory redisConnectionFactory() { + RedisStandaloneConfiguration redisConfiguration = new RedisStandaloneConfiguration(redisHost, redisPort); + redisConfiguration.setPassword(redisPwd); + LettuceClientConfiguration lettuceConfig = LettuceClientConfiguration.builder().useSsl().build(); + return new LettuceConnectionFactory(redisConfiguration, lettuceConfig); + } + + @Bean + @Qualifier("redisTemplate") + public RedisTemplate redisObjectTemplate(final LettuceConnectionFactory connectionFactory, ObjectMapper objectMapper) { + RedisTemplate template = new RedisTemplate<>(); + template.setKeySerializer(new StringRedisSerializer()); + final var objectRedisSerializer = new ObjectRedisSerializer(); + template.setValueSerializer(objectRedisSerializer); + template.setConnectionFactory(connectionFactory); + return template; + } +} diff --git a/src/main/java/it/gov/pagopa/mocker/controller/WebConf.java b/src/main/java/it/gov/pagopa/mocker/config/WebConf.java similarity index 89% rename from src/main/java/it/gov/pagopa/mocker/controller/WebConf.java rename to src/main/java/it/gov/pagopa/mocker/config/WebConf.java index fa83f5a..cc8c992 100644 --- a/src/main/java/it/gov/pagopa/mocker/controller/WebConf.java +++ b/src/main/java/it/gov/pagopa/mocker/config/WebConf.java @@ -1,7 +1,8 @@ -package it.gov.pagopa.mocker.controller; +package it.gov.pagopa.mocker.config; import javax.servlet.http.HttpServlet; +import it.gov.pagopa.mocker.controller.ProxyServlet; import it.gov.pagopa.mocker.util.Constants; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.web.servlet.ServletRegistrationBean; diff --git a/src/main/java/it/gov/pagopa/mocker/controller/ProxyServlet.java b/src/main/java/it/gov/pagopa/mocker/controller/ProxyServlet.java index f270b9e..9d09442 100644 --- a/src/main/java/it/gov/pagopa/mocker/controller/ProxyServlet.java +++ b/src/main/java/it/gov/pagopa/mocker/controller/ProxyServlet.java @@ -1,11 +1,11 @@ package it.gov.pagopa.mocker.controller; +import it.gov.pagopa.mocker.service.ProxyService; import it.gov.pagopa.mocker.util.Constants; import it.gov.pagopa.mocker.model.AppInfo; import it.gov.pagopa.mocker.model.ExtractedRequest; import it.gov.pagopa.mocker.model.ExtractedResponse; import it.gov.pagopa.mocker.service.HealthCheckService; -import it.gov.pagopa.mocker.service.MockerService; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; @@ -24,7 +24,7 @@ public class ProxyServlet extends HttpServlet { @Autowired - private MockerService mockerService; + private ProxyService proxyService; @Autowired private HealthCheckService healthCheckService; @@ -75,9 +75,10 @@ private void analyzeRequest(HttpServletRequest request, HttpServletResponse resp try { /* Extract body from HttpServletRequest request and analyze all. */ long start = System.nanoTime(); - String body = request.getReader().lines().collect(Collectors.joining(System.lineSeparator())); log.info(String.format("Trying to mocking the response for the called resource: [%s]", request.getRequestURI())); - ExtractedResponse extractedResponse = mockerService.analyze(ExtractedRequest.extract(request, body)); + String body = request.getReader().lines().collect(Collectors.joining(System.lineSeparator())); + /* Extracting mock response */ + ExtractedResponse extractedResponse = proxyService.extract(ExtractedRequest.extract(request, body)); /* Update HttpServletResponse response */ response.setStatus(extractedResponse.getStatus()); response.setCharacterEncoding("UTF-8"); diff --git a/src/main/java/it/gov/pagopa/mocker/model/ExtractedRequest.java b/src/main/java/it/gov/pagopa/mocker/model/ExtractedRequest.java index 6c52bc2..429b77e 100644 --- a/src/main/java/it/gov/pagopa/mocker/model/ExtractedRequest.java +++ b/src/main/java/it/gov/pagopa/mocker/model/ExtractedRequest.java @@ -15,15 +15,20 @@ public class ExtractedRequest { private final String id; + private final String url; + private final String contentType; + private final String body; + private final Map headers; + private final Map queryParameters; private ExtractedRequest(HttpServletRequest request, String body) { this.url = request.getRequestURI().replace(Constants.MOCKER_PATH_ROOT, Constants.EMPTY_STRING); - this.id = Utility.generateID(this.url, request.getMethod().toLowerCase()); + this.id = Utility.generateHash(this.url, request.getMethod().toLowerCase()); this.body = body; this.headers = extractHeaders(request); this.contentType = (this.headers.isEmpty() || this.headers.get(Constants.HEADER_CONTENTTYPE) == null) ? Constants.APPLICATION_JSON : this.headers.get(Constants.HEADER_CONTENTTYPE); diff --git a/src/main/java/it/gov/pagopa/mocker/model/ExtractedResponse.java b/src/main/java/it/gov/pagopa/mocker/model/ExtractedResponse.java index 38d640b..b72d731 100644 --- a/src/main/java/it/gov/pagopa/mocker/model/ExtractedResponse.java +++ b/src/main/java/it/gov/pagopa/mocker/model/ExtractedResponse.java @@ -10,6 +10,7 @@ @Setter @Builder public class ExtractedResponse { + private boolean isCacheable; private String body; private int status; private Map headers; diff --git a/src/main/java/it/gov/pagopa/mocker/service/CacheService.java b/src/main/java/it/gov/pagopa/mocker/service/CacheService.java new file mode 100644 index 0000000..f60bb1d --- /dev/null +++ b/src/main/java/it/gov/pagopa/mocker/service/CacheService.java @@ -0,0 +1,28 @@ +package it.gov.pagopa.mocker.service; + +import it.gov.pagopa.mocker.model.ExtractedResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; + +import java.util.concurrent.TimeUnit; + +@Component +@Slf4j +public class CacheService { + + @Autowired + @Qualifier("redisTemplate") + private RedisTemplate template; + + public ExtractedResponse get(String key, String hashKey) { + return (ExtractedResponse) template.opsForHash().get(key, hashKey); + } + + public void set(String key, String hashKey, ExtractedResponse hashValue) { + template.expire(key, 5, TimeUnit.DAYS); + template.opsForHash().put(key, hashKey, hashValue); + } +} \ No newline at end of file diff --git a/src/main/java/it/gov/pagopa/mocker/service/ProxyService.java b/src/main/java/it/gov/pagopa/mocker/service/ProxyService.java new file mode 100644 index 0000000..72c3aa9 --- /dev/null +++ b/src/main/java/it/gov/pagopa/mocker/service/ProxyService.java @@ -0,0 +1,62 @@ +package it.gov.pagopa.mocker.service; + +import it.gov.pagopa.mocker.model.ExtractedRequest; +import it.gov.pagopa.mocker.model.ExtractedResponse; +import it.gov.pagopa.mocker.util.Constants; +import it.gov.pagopa.mocker.util.Utility; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.*; +import java.util.stream.Collectors; + +@Service +@Slf4j +public class ProxyService { + + @Autowired + private MockerService mockerService; + + @Autowired + private CacheService cacheService; + + public ExtractedResponse extract(ExtractedRequest extractedRequest) { + + String hashedID = extractedRequest.getId(); + String headers = extractHeaderSubstring(extractedRequest.getHeaders()); + String queryParams = extractQueryParameterSubstring(extractedRequest.getQueryParameters()); + String body = extractedRequest.getBody(); + String hashedRequest = Utility.generateHash(headers, queryParams, body); + + ExtractedResponse response = cacheService.get(hashedID, hashedRequest); + if (response == null) { + response = mockerService.analyze(extractedRequest); + if (response != null && response.isCacheable()) { + cacheService.set(hashedID, hashedRequest, response); + } + } + return response; + } + + private String extractHeaderSubstring(Map headers) { + List formattedHeaders = headers.keySet() + .stream() + .sorted() + .filter(headerKey -> !Constants.NOT_CACHEABLE_HEADERS.contains(headerKey)) + .map(headerKey -> String.format("\"%s\":\"%s\"", headerKey, headers.get(headerKey))) + .collect(Collectors.toList()); + return "headers:" + formattedHeaders.toString() + ";"; + } + + private String extractQueryParameterSubstring(Map queryParameters) { + List formattedQueryParameters = queryParameters.keySet() + .stream() + .sorted() + .filter(queryParamKey -> !Utility.isNullOrEmpty(queryParameters.get(queryParamKey))) + .map(queryParamKey -> String.format("\"%s\":\"%s\"", queryParamKey, queryParameters.get(queryParamKey))) + .collect(Collectors.toList()); + return "queryparams:" + formattedQueryParameters.toString() + ";"; + } + +} diff --git a/src/main/java/it/gov/pagopa/mocker/service/validator/ResourceExtractor.java b/src/main/java/it/gov/pagopa/mocker/service/validator/ResourceExtractor.java index dcebe11..5757536 100644 --- a/src/main/java/it/gov/pagopa/mocker/service/validator/ResourceExtractor.java +++ b/src/main/java/it/gov/pagopa/mocker/service/validator/ResourceExtractor.java @@ -208,6 +208,7 @@ private ExtractedResponse getMockResponse(MockRuleEntity mockRule, UnmarshalledB } return ExtractedResponse.builder() .body(decodedBody) + .isCacheable(true) .status(mockResponse.getStatus()) .headers(headers) .build(); diff --git a/src/main/java/it/gov/pagopa/mocker/service/validator/ResponseBuilder.java b/src/main/java/it/gov/pagopa/mocker/service/validator/ResponseBuilder.java index fec378d..d39d509 100644 --- a/src/main/java/it/gov/pagopa/mocker/service/validator/ResponseBuilder.java +++ b/src/main/java/it/gov/pagopa/mocker/service/validator/ResponseBuilder.java @@ -19,11 +19,11 @@ public static ExtractedResponse buildErrorResponse(String message, ExtractedRequ String body = getDefaultMessageByContentType(message, contentType); Map headers = request.getHeaders(); headers.put(Constants.HEADER_CONTENTTYPE, contentType); - return buildResponse(500, body, headers); + return buildResponse(false, 500, body, headers); } - private static ExtractedResponse buildResponse(int httpStatus, String body, Map headers) { - return ExtractedResponse.builder().body(body).status(httpStatus).headers(headers).build(); + private static ExtractedResponse buildResponse(boolean isCacheable, int httpStatus, String body, Map headers) { + return ExtractedResponse.builder().isCacheable(isCacheable).body(body).status(httpStatus).headers(headers).build(); } private static String getDefaultMessageByContentType(String message, String contentType) { diff --git a/src/main/java/it/gov/pagopa/mocker/util/Constants.java b/src/main/java/it/gov/pagopa/mocker/util/Constants.java index 1915d21..d950122 100644 --- a/src/main/java/it/gov/pagopa/mocker/util/Constants.java +++ b/src/main/java/it/gov/pagopa/mocker/util/Constants.java @@ -1,5 +1,9 @@ package it.gov.pagopa.mocker.util; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + public class Constants { public static final String APPLICATION_JSON = "application/json"; @@ -26,6 +30,12 @@ public class Constants { public static final String EMPTY_STRING = ""; + public static final Set NOT_CACHEABLE_HEADERS = Set.of( + "authorization", "age", "etag", + "expires", "if-modified-since", "if-none-match", + "last-modified", "user-agent" + ); + public static final String WHITESPACE = " "; diff --git a/src/main/java/it/gov/pagopa/mocker/util/ObjectRedisSerializer.java b/src/main/java/it/gov/pagopa/mocker/util/ObjectRedisSerializer.java new file mode 100644 index 0000000..cbe6dac --- /dev/null +++ b/src/main/java/it/gov/pagopa/mocker/util/ObjectRedisSerializer.java @@ -0,0 +1,38 @@ +package it.gov.pagopa.mocker.util; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; +import lombok.SneakyThrows; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +public class ObjectRedisSerializer implements RedisSerializer { + + @SneakyThrows + @Override + public byte[] serialize(T value) throws SerializationException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + GZIPOutputStream gzipOut = new GZIPOutputStream(baos); + ObjectOutputStream objectOut = new ObjectOutputStream(gzipOut); + objectOut.writeObject(value); + objectOut.close(); + return baos.toByteArray(); + } + + @SneakyThrows + @Override + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes != null) { + ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + GZIPInputStream gzipIn = new GZIPInputStream(bais); + ObjectInputStream objectIn = new ObjectInputStream(gzipIn); + return (T) objectIn.readObject(); + } else { + return null; + } + } +} \ No newline at end of file diff --git a/src/main/java/it/gov/pagopa/mocker/util/Utility.java b/src/main/java/it/gov/pagopa/mocker/util/Utility.java index eb7d428..003d154 100644 --- a/src/main/java/it/gov/pagopa/mocker/util/Utility.java +++ b/src/main/java/it/gov/pagopa/mocker/util/Utility.java @@ -12,16 +12,24 @@ public class Utility { private Utility() {} - public static String generateID(String url, String httpMethod) { - String hashedId = ""; + public static String generateHash(String... content) { + String hashedContent = ""; try { - byte[] requestIdBytes = httpMethod.concat(Constants.WHITESPACE).concat(url).getBytes(StandardCharsets.UTF_8); + StringBuilder builder = new StringBuilder(); + Iterator it = Arrays.stream(content).iterator(); + while (it.hasNext()) { + builder.append(it.next()); + if (it.hasNext()) { + builder.append(Constants.WHITESPACE); + } + } + byte[] requestIdBytes = builder.toString().getBytes(StandardCharsets.UTF_8); MessageDigest md = MessageDigest.getInstance("MD5"); - hashedId = new String(md.digest(requestIdBytes)); + hashedContent = new String(md.digest(requestIdBytes)); } catch (NoSuchAlgorithmException e) { - log.error("Error while generating the hash value from URL and HTTP method. No valid algorithm found as 'MD5'.", e); + log.error("Error while generating the hash value from objects. No valid algorithm found as 'MD5'.", e); } - return hashedId; + return hashedContent; } public static boolean isNullOrEmpty(String content) { diff --git a/src/main/resources/application-h2.properties b/src/main/resources/application-h2.properties index a063d17..749bcbd 100644 --- a/src/main/resources/application-h2.properties +++ b/src/main/resources/application-h2.properties @@ -22,4 +22,8 @@ spring.sql.init.data-locations=classpath:/h2/schema-h2.sql,classpath:/h2/data-h2 logging.level.root=INFO logging.level.org.springframework=INFO logging.level.it.gov.pagopa.mocker=DEBUG -logging.level.org.hibernate=ERROR \ No newline at end of file +logging.level.org.hibernate=ERROR + +redis.host=${REDIS_HOST} +redis.port=${REDIS_PORT} +redis.pwd=${REDIS_PASSWORD} \ No newline at end of file diff --git a/src/main/resources/application-local.properties b/src/main/resources/application-local.properties index 226a5fb..c98e5fb 100644 --- a/src/main/resources/application-local.properties +++ b/src/main/resources/application-local.properties @@ -10,8 +10,15 @@ spring.datasource.password=${DB_PASSWORD} spring.datasource.driver-class-name=org.postgresql.Driver spring.jpa.properties.hibernate.default_schema=mocker spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect +spring.jpa.show-sql=true + +healthcheck.query=${HEALTHCHECK_QUERY:select 1} logging.level.root=INFO logging.level.org.springframework=INFO logging.level.it.gov.pagopa.mocker=DEBUG -logging.level.org.hibernate=ERROR \ No newline at end of file +logging.level.org.hibernate=ERROR + +redis.host=${REDIS_HOST} +redis.port=${REDIS_PORT} +redis.pwd=${REDIS_PASSWORD} \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 8ba3b69..2fca346 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -17,4 +17,8 @@ healthcheck.query=${HEALTHCHECK_QUERY:select 1} logging.level.root=${DEFAULT_LOGGING_LEVEL:INFO} logging.level.org.springframework=${DEFAULT_LOGGING_LEVEL:INFO} logging.level.it.gov.pagopa.mocker=${APP_LOGGING_LEVEL:INFO} -logging.level.org.hibernate=ERROR \ No newline at end of file +logging.level.org.hibernate=ERROR + +redis.host=${REDIS_HOST} +redis.port=${REDIS_PORT} +redis.pwd=${REDIS_PASSWORD} \ No newline at end of file diff --git a/src/test/java/it/gov/pagopa/mocker/util/UtilityTest.java b/src/test/java/it/gov/pagopa/mocker/util/UtilityTest.java index c3583f3..567536c 100644 --- a/src/test/java/it/gov/pagopa/mocker/util/UtilityTest.java +++ b/src/test/java/it/gov/pagopa/mocker/util/UtilityTest.java @@ -20,7 +20,7 @@ void testGenerateID() { String httpMethod = "GET"; byte[] requestIdBytes = httpMethod.concat(Constants.WHITESPACE).concat(url).getBytes(StandardCharsets.UTF_8); MessageDigest md = MessageDigest.getInstance("MD5"); - assertEquals(new String(md.digest(requestIdBytes)), Utility.generateID(url, httpMethod)); + assertEquals(new String(md.digest(requestIdBytes)), Utility.generateHash(url, httpMethod)); } @Test From 4ae02cd2aa7e818f4d5f7a92fdff99c62a702fd4 Mon Sep 17 00:00:00 2001 From: Andrea De Rinaldis Date: Thu, 5 Oct 2023 09:05:11 +0200 Subject: [PATCH 3/7] fix: updated several methods after test session in local --- .../gov/pagopa/mocker/config/RedisConf.java | 19 +++++---- .../mocker/model/ExtractedResponse.java | 3 +- .../pagopa/mocker/service/CacheService.java | 10 ++--- .../pagopa/mocker/service/ProxyService.java | 6 ++- .../it/gov/pagopa/mocker/util/Constants.java | 4 +- .../it/gov/pagopa/mocker/util/Utility.java | 16 +++++++- src/main/resources/h2/data-h2.sql | 39 +++++++++++-------- 7 files changed, 63 insertions(+), 34 deletions(-) diff --git a/src/main/java/it/gov/pagopa/mocker/config/RedisConf.java b/src/main/java/it/gov/pagopa/mocker/config/RedisConf.java index 990eb79..3fe8de1 100644 --- a/src/main/java/it/gov/pagopa/mocker/config/RedisConf.java +++ b/src/main/java/it/gov/pagopa/mocker/config/RedisConf.java @@ -9,22 +9,24 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; import org.springframework.data.redis.connection.RedisStandaloneConfiguration; import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; @Configuration public class RedisConf { - @Value("${redis.host}") + @Value("${spring.redis.host}") private String redisHost; - @Value("${redis.port}") + @Value("${spring.redis.port}") private int redisPort; - @Value("${redis.pwd}") + @Value("${spring.redis.pwd}") private String redisPwd; @Bean @@ -43,12 +45,13 @@ public LettuceConnectionFactory redisConnectionFactory() { } @Bean - @Qualifier("redisTemplate") - public RedisTemplate redisObjectTemplate(final LettuceConnectionFactory connectionFactory, ObjectMapper objectMapper) { - RedisTemplate template = new RedisTemplate<>(); + @Qualifier("extractedRequest") + public RedisTemplate redisObjectTemplate(final LettuceConnectionFactory connectionFactory, ObjectMapper objectMapper) { + RedisTemplate template = new RedisTemplate<>(); template.setKeySerializer(new StringRedisSerializer()); - final var objectRedisSerializer = new ObjectRedisSerializer(); - template.setValueSerializer(objectRedisSerializer); + final var jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class); + jackson2JsonRedisSerializer.setObjectMapper(objectMapper); + template.setValueSerializer(jackson2JsonRedisSerializer); template.setConnectionFactory(connectionFactory); return template; } diff --git a/src/main/java/it/gov/pagopa/mocker/model/ExtractedResponse.java b/src/main/java/it/gov/pagopa/mocker/model/ExtractedResponse.java index b72d731..9080207 100644 --- a/src/main/java/it/gov/pagopa/mocker/model/ExtractedResponse.java +++ b/src/main/java/it/gov/pagopa/mocker/model/ExtractedResponse.java @@ -4,12 +4,13 @@ import lombok.Getter; import lombok.Setter; +import java.io.Serializable; import java.util.Map; @Getter @Setter @Builder -public class ExtractedResponse { +public class ExtractedResponse implements Serializable { private boolean isCacheable; private String body; private int status; diff --git a/src/main/java/it/gov/pagopa/mocker/service/CacheService.java b/src/main/java/it/gov/pagopa/mocker/service/CacheService.java index f60bb1d..d7aff50 100644 --- a/src/main/java/it/gov/pagopa/mocker/service/CacheService.java +++ b/src/main/java/it/gov/pagopa/mocker/service/CacheService.java @@ -14,15 +14,15 @@ public class CacheService { @Autowired - @Qualifier("redisTemplate") - private RedisTemplate template; + @Qualifier("extractedRequest") + private RedisTemplate extractedRequest; public ExtractedResponse get(String key, String hashKey) { - return (ExtractedResponse) template.opsForHash().get(key, hashKey); + return (ExtractedResponse) extractedRequest.opsForHash().get(key, hashKey); } public void set(String key, String hashKey, ExtractedResponse hashValue) { - template.expire(key, 5, TimeUnit.DAYS); - template.opsForHash().put(key, hashKey, hashValue); + extractedRequest.expire(key, 5, TimeUnit.DAYS); + extractedRequest.opsForHash().put(key, hashKey, hashValue); } } \ No newline at end of file diff --git a/src/main/java/it/gov/pagopa/mocker/service/ProxyService.java b/src/main/java/it/gov/pagopa/mocker/service/ProxyService.java index 72c3aa9..3ffe19e 100644 --- a/src/main/java/it/gov/pagopa/mocker/service/ProxyService.java +++ b/src/main/java/it/gov/pagopa/mocker/service/ProxyService.java @@ -29,10 +29,14 @@ public ExtractedResponse extract(ExtractedRequest extractedRequest) { String body = extractedRequest.getBody(); String hashedRequest = Utility.generateHash(headers, queryParams, body); + log.trace(String.format("Extracted headers: [%s] Extracted query parameter: [%s]", headers, queryParams)); + log.debug(String.format("Retrieving mocked response from cache using the id [%s:%s].", hashedID, hashedRequest)); ExtractedResponse response = cacheService.get(hashedID, hashedRequest); if (response == null) { + log.debug("No mocked response found in cache. Trying to retrieve it from database."); response = mockerService.analyze(extractedRequest); if (response != null && response.isCacheable()) { + log.debug(String.format("The found mock response will be cached using the id [%s:%s].", hashedID, hashedRequest)); cacheService.set(hashedID, hashedRequest, response); } } @@ -43,7 +47,7 @@ private String extractHeaderSubstring(Map headers) { List formattedHeaders = headers.keySet() .stream() .sorted() - .filter(headerKey -> !Constants.NOT_CACHEABLE_HEADERS.contains(headerKey)) + .filter(headerKey -> !Constants.NOT_CACHEABLE_HEADERS.contains(headerKey.toLowerCase())) .map(headerKey -> String.format("\"%s\":\"%s\"", headerKey, headers.get(headerKey))) .collect(Collectors.toList()); return "headers:" + formattedHeaders.toString() + ";"; diff --git a/src/main/java/it/gov/pagopa/mocker/util/Constants.java b/src/main/java/it/gov/pagopa/mocker/util/Constants.java index d950122..af5016f 100644 --- a/src/main/java/it/gov/pagopa/mocker/util/Constants.java +++ b/src/main/java/it/gov/pagopa/mocker/util/Constants.java @@ -33,7 +33,9 @@ public class Constants { public static final Set NOT_CACHEABLE_HEADERS = Set.of( "authorization", "age", "etag", "expires", "if-modified-since", "if-none-match", - "last-modified", "user-agent" + "last-modified", "user-agent", + // custom variable headers + "postman-token" ); public static final String WHITESPACE = " "; diff --git a/src/main/java/it/gov/pagopa/mocker/util/Utility.java b/src/main/java/it/gov/pagopa/mocker/util/Utility.java index 003d154..5608716 100644 --- a/src/main/java/it/gov/pagopa/mocker/util/Utility.java +++ b/src/main/java/it/gov/pagopa/mocker/util/Utility.java @@ -13,6 +13,7 @@ public class Utility { private Utility() {} public static String generateHash(String... content) { + System.out.println("CONTENT: " + content[0] + " " + content[1]); String hashedContent = ""; try { StringBuilder builder = new StringBuilder(); @@ -25,13 +26,26 @@ public static String generateHash(String... content) { } byte[] requestIdBytes = builder.toString().getBytes(StandardCharsets.UTF_8); MessageDigest md = MessageDigest.getInstance("MD5"); - hashedContent = new String(md.digest(requestIdBytes)); + byte[] digestByteArray = md.digest(requestIdBytes); + + StringBuilder hashStringBuilder = new StringBuilder(); + for (byte b : digestByteArray) { + if ((0xff & b) < 0x10) { + hashStringBuilder.append('0'); + } + hashStringBuilder.append(Integer.toHexString(0xff & b)); + } + hashedContent = hashStringBuilder.toString(); } catch (NoSuchAlgorithmException e) { log.error("Error while generating the hash value from objects. No valid algorithm found as 'MD5'.", e); } return hashedContent; } + public static void main(String[] args) { + System.out.println(Utility.generateHash("/gpd-reporting-orgs-enrollment/api/v1/organizations/99999999999", "get")); + } + public static boolean isNullOrEmpty(String content) { return content == null || Constants.EMPTY_STRING.equals(content); } diff --git a/src/main/resources/h2/data-h2.sql b/src/main/resources/h2/data-h2.sql index e60ef00..b2bf58d 100644 --- a/src/main/resources/h2/data-h2.sql +++ b/src/main/resources/h2/data-h2.sql @@ -1,29 +1,34 @@ -INSERT INTO mocker.tag(id, "value") VALUES('398ddf77-8012-4767-84aa-87ad194d3ac9', 'EC'); -INSERT INTO mocker.tag(id, "value") VALUES('261af795-2652-401e-a9c2-dcc160041bf6', 'GPD'); -INSERT INTO mocker.tag(id, "value") VALUES('eaa80a30-2992-47fc-b607-4a248d03066b', 'ORGS ENROLLMENT'); -INSERT INTO mocker.tag(id, "value") VALUES('88513e6d-7229-43ea-96b5-f83ffd96d5f5', 'MAIN RULE'); +INSERT INTO mocker.mock_resource(id, subsystem_url, resource_url, http_method, "name", is_active) VALUES +('ee743fac8ef18b7915c4213d1de18923', 'gpd-reporting-orgs-enrollment/api/v1', 'organizations/77777777777', 'GET', 'Get enrolled organization with ID 77777777777', true), +('495983b742d7e4bfc9afcbe002e2f07d', 'gpd-reporting-orgs-enrollment/api/v1', 'organizations/88888888888', 'GET', 'Get enrolled organization with ID 88888888888', true), +('fb7adf5bce2afe832d407a05054607a7', 'gpd-reporting-orgs-enrollment/api/v1', 'organizations/99999999999', 'GET', 'Get enrolled organization with ID 99999999999', true); -INSERT INTO mocker.mock_resource(id, subsystem_url, resource_url, http_method, "name", is_active) -VALUES('c7b8221105a531da9a731f334d176984', 'gpd-reporting-orgs-enrollment/api/v1', 'organizations/77777777777', 'GET', 'Get enrolled organization with ID 77777777777', true); +INSERT INTO mocker.mock_response(id, body, status) VALUES +('26e05a1f-9621-4e24-a57d-28694ff30306', 'ewogICAgIm9yZ2FuaXphdGlvbkZpc2NhbENvZGUiOiAiNzc3Nzc3Nzc3NzciLAogICAgIm9yZ2FuaXphdGlvbk9uYm9hcmRpbmdEYXRlIjogIjIwMjMtMDYtMjBUMTU6MDM6NTYuODYyNjQxIgp9', 200), +('26e05a1f-9621-4e24-a57d-28694ff30307', 'ewogICAgInN0YXR1cyI6IDQwNCwKICAgICJ0aXRsZSI6ICJOb3QgZm91bmQiLAogICAgIm1lc3NhZ2UiOiAiTm8gdmFsaWQgb3JnYW5pemF0aW9uIGZvdW5kIHdpdGggaWQgWzg4ODg4ODg4ODg4XSIsCn0=', 404), +('26e05a1f-9621-4e24-a57d-28694ff30308', 'ewogICAgIm9yZ2FuaXphdGlvbkZpc2NhbENvZGUiOiAiOTk5OTk5OTk5OTkiLAogICAgIm9yZ2FuaXphdGlvbk9uYm9hcmRpbmdEYXRlIjogIjIwMjMtMTItMDFUMDg6MDA6MDAuMDAwIgp9', 200); -INSERT INTO mocker.mock_response(id, body, status) -VALUES('26e05a1f-9621-4e24-a57d-28694ff30306', 'ewogICAgIm9yZ2FuaXphdGlvbkZpc2NhbENvZGUiOiAiNzc3Nzc3Nzc3NzciLAogICAgIm9yZ2FuaXphdGlvbk9uYm9hcmRpbmdEYXRlIjogIjIwMjMtMDYtMjBUMTU6MDM6NTYuODYyNjQxIgp9', 200); +INSERT INTO mocker.response_header(response_id, "header", "value") VALUES +('26e05a1f-9621-4e24-a57d-28694ff30306', 'Content-Type', 'application/json'), +('26e05a1f-9621-4e24-a57d-28694ff30306', 'X-Some-Header', 'some-strange-header-abcd'), +('26e05a1f-9621-4e24-a57d-28694ff30307', 'Content-Type', 'application/json'), +('26e05a1f-9621-4e24-a57d-28694ff30308', 'Content-Type', 'application/json'), +('26e05a1f-9621-4e24-a57d-28694ff30308', 'X-Some-Header', 'some-strange-header-wxyz'); -INSERT INTO mocker.response_header(response_id, "header", "value") -VALUES('26e05a1f-9621-4e24-a57d-28694ff30306', 'Content-Type', 'application/json'); +INSERT INTO mocker.mock_rule(id, "name", "order", is_active, resource_id, response_id) VALUES +('6c08a21c-6a92-4f6b-a1e1-bf68c4e099c9', 'Main rule', 1, true, 'ee743fac8ef18b7915c4213d1de18923', '26e05a1f-9621-4e24-a57d-28694ff30306'), +('6c08a21c-6a92-4f6b-a1e1-bf68c4e099d0', 'Main rule', 1, true, '495983b742d7e4bfc9afcbe002e2f07d', '26e05a1f-9621-4e24-a57d-28694ff30307'), +('6c08a21c-6a92-4f6b-a1e1-bf68c4e099d9', 'Main rule', 1, true, 'fb7adf5bce2afe832d407a05054607a7', '26e05a1f-9621-4e24-a57d-28694ff30308'); -INSERT INTO mocker.mock_rule(id, "name", "order", is_active, resource_id, response_id) -VALUES('6c08a21c-6a92-4f6b-a1e1-bf68c4e099c9', 'Main rule', 1, true, 'c7b8221105a531da9a731f334d176984', '26e05a1f-9621-4e24-a57d-28694ff30306'); - - - -INSERT INTO mocker.mock_condition(id, "order", field_position, content_type, field_name, condition_type, condition_value, rule_id) -VALUES('6b0b003d-74f4-428e-b950-61f42e02bf07', 1, 'HEADER', 'STRING', 'ClientId', 'NULL', '', '6c08a21c-6a92-4f6b-a1e1-bf68c4e099c9'); +INSERT INTO mocker.mock_condition(id, "order", field_position, content_type, field_name, condition_type, condition_value, rule_id) VALUES +('6b0b003d-74f4-428e-b950-61f42e02bf07', 1, 'HEADER', 'STRING', 'ClientId', 'NULL', '', '6c08a21c-6a92-4f6b-a1e1-bf68c4e099c9'), +('6b0b003d-74f4-428e-b950-61f42e02bf08', 1, 'HEADER', 'STRING', 'ClientId', 'NULL', '', '6c08a21c-6a92-4f6b-a1e1-bf68c4e099d0'), +('6b0b003d-74f4-428e-b950-61f42e02bf09', 1, 'HEADER', 'STRING', 'ClientId', 'NULL', '', '6c08a21c-6a92-4f6b-a1e1-bf68c4e099d9'); From e4b3b66bcc256a7451381639daa755f02df55d43 Mon Sep 17 00:00:00 2001 From: Andrea De Rinaldis Date: Mon, 9 Oct 2023 16:17:07 +0200 Subject: [PATCH 4/7] fix: added precommit plugin --- .pre-commit-config.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .pre-commit-config.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..0d2e1f8 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,11 @@ +# 1. `pip install pre-commit` +# 2. `pre-commit install` +# 3. set GITGUARDIAN_API_KEY in your develop environment (get an api key here: https://dashboard.gitguardian.com/workspace/230910/settings/personal/personal-access-tokens) +# more info https://docs.gitguardian.com/internal-repositories-monitoring/integrations/git_hooks/pre_commit +repos: + - repo: https://github.com/gitguardian/ggshield + rev: v1.11.0 + hooks: + - id: ggshield + language_version: python3 + stages: [ commit ] From b5008558579d06aa1a974dce62edd38c592f1608 Mon Sep 17 00:00:00 2001 From: Andrea De Rinaldis Date: Mon, 9 Oct 2023 16:42:41 +0200 Subject: [PATCH 5/7] fix: added missing variable and secrets --- .cache_ggshield | 1 + helm/values-dev.yaml | 7 +++- helm/values-uat.yaml | 91 +++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 .cache_ggshield diff --git a/.cache_ggshield b/.cache_ggshield new file mode 100644 index 0000000..e59b65d --- /dev/null +++ b/.cache_ggshield @@ -0,0 +1 @@ +{"last_found_secrets": [{"name": "PostgreSQL Credentials - helm/values-dev.yaml", "match": "823048a392b266d9d4d1c0fdc4cc168c5959eb064493e0d4f8ca31b35f4be37e"}, {"name": "PostgreSQL Credentials - helm/values-uat.yaml", "match": "d2844f4b10103d2e07be01d8ccf0cc7ead5f5c5392729b0e9b1c10693f815653"}]} \ No newline at end of file diff --git a/helm/values-dev.yaml b/helm/values-dev.yaml index 5de824d..fe774a6 100644 --- a/helm/values-dev.yaml +++ b/helm/values-dev.yaml @@ -60,19 +60,22 @@ microservice-chart: type: Utilization # Allowed types are 'Utilization' or 'AverageValue' value: "75" envConfig: - WEBSITE_SITE_NAME: 'pagopamocker' # required to show cloud role name in application insights + WEBSITE_SITE_NAME: 'pagopamocker' APPLICATIONINSIGHTS_CONNECTION_STRING: 'ai-connection-string' APPLICATIONINSIGHTS_ROLE_NAME: "pagopa-mocker" ENV: 'aks-dev' APP_LOGGING_LEVEL: 'DEBUG' DEFAULT_LOGGING_LEVEL: 'INFO' - SPRING_DATASOURCE_URL: 'jdbc:postgresql://pagopa-d-mocker-psql.postgres.database.azure.com/mocker' SPRING_DATASOURCE_DRIVER: 'org.postgresql.Driver' SPRING_JPA_DB_PLATFORM: 'org.hibernate.dialect.PostgreSQLDialect' DATABASE_SCHEMA: 'mocker' + REDIS_HOST: "pagopa-d-redis.redis.cache.windows.net" + REDIS_PORT: "6380" envSecret: + SPRING_DATASOURCE_URL: 'db-mocker-url' SPRING_DATASOURCE_USERNAME: 'db-mocker-user-name' SPRING_DATASOURCE_PASSWORD: 'db-mocker-user-pwd' + REDIS_PASSWORD: 'redis-password' keyvault: name: "pagopa-d-mock-kv" tenantId: "7788edaf-0346-4068-9d79-c868aed15b3d" diff --git a/helm/values-uat.yaml b/helm/values-uat.yaml index 33cba17..1e5c996 100644 --- a/helm/values-uat.yaml +++ b/helm/values-uat.yaml @@ -1,6 +1,95 @@ microservice-chart: + namespace: "mock" + nameOverride: "" + fullnameOverride: "" image: - tag: 1.0.2 + repository: ghcr.io/pagopa/pagopa-mocker + tag: "1.0.2" + pullPolicy: Always + livenessProbe: + httpGet: + path: /mocker/info + port: 8080 + initialDelaySeconds: 90 + failureThreshold: 6 + periodSeconds: 10 + readinessProbe: + httpGet: + path: /mocker/info + port: 8080 + initialDelaySeconds: 90 + failureThreshold: 6 + periodSeconds: 10 + deployment: + create: true + service: + create: true + type: ClusterIP + port: 8080 + ingress: + create: true + host: "weudev.mock.internal.dev.platform.pagopa.it" + path: /pagopa-mocker/(.*) + serviceAccount: + create: false + annotations: {} + name: "" + podAnnotations: {} + podSecurityContext: + seccompProfile: + type: RuntimeDefault + securityContext: + allowPrivilegeEscalation: false + resources: + requests: + memory: "512Mi" + cpu: "0.25" + limits: + memory: "512Mi" + cpu: "0.25" + autoscaling: + enable: true + minReplica: 1 + maxReplica: 10 + pollingInterval: 10 # seconds + cooldownPeriod: 50 # seconds + triggers: + - type: cpu + metadata: + # Required + type: Utilization # Allowed types are 'Utilization' or 'AverageValue' + value: "75" + envConfig: + WEBSITE_SITE_NAME: 'pagopamocker' + APPLICATIONINSIGHTS_CONNECTION_STRING: 'ai-connection-string' + APPLICATIONINSIGHTS_ROLE_NAME: "pagopa-mocker" + ENV: 'aks-dev' + APP_LOGGING_LEVEL: 'DEBUG' + DEFAULT_LOGGING_LEVEL: 'INFO' + SPRING_DATASOURCE_DRIVER: 'org.postgresql.Driver' + SPRING_JPA_DB_PLATFORM: 'org.hibernate.dialect.PostgreSQLDialect' + DATABASE_SCHEMA: 'mocker' + REDIS_HOST: "pagopa-d-redis.redis.cache.windows.net" + REDIS_PORT: "6380" + envSecret: + SPRING_DATASOURCE_URL: 'db-mocker-url' + SPRING_DATASOURCE_USERNAME: 'db-mocker-user-name' + SPRING_DATASOURCE_PASSWORD: 'db-mocker-user-pwd' + REDIS_PASSWORD: 'redis-password' + keyvault: + name: "pagopa-u-mock-kv" + tenantId: "7788edaf-0346-4068-9d79-c868aed15b3d" + nodeSelector: {} + tolerations: [] + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: node_type + operator: In + values: + - user canaryDelivery: deployment: image: From 791d91b0464aba7411bfa43328830d4306676988 Mon Sep 17 00:00:00 2001 From: pagopa-github-bot Date: Mon, 9 Oct 2023 15:12:57 +0000 Subject: [PATCH 6/7] Bump to version 1.0.2-1-infrastructure-optimization [skip ci] --- helm/Chart.yaml | 4 ++-- helm/values-dev.yaml | 3 ++- helm/values-uat.yaml | 3 ++- pom.xml | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/helm/Chart.yaml b/helm/Chart.yaml index 11959fb..cb509ef 100644 --- a/helm/Chart.yaml +++ b/helm/Chart.yaml @@ -2,8 +2,8 @@ apiVersion: v2 name: pagopa-mocker description: Microservice that permits to dynamically generate mocked responses type: application -version: 1.6.0 -appVersion: 1.0.2 +version: 1.7.0 +appVersion: 1.0.2-1-infrastructure-optimization dependencies: - name: microservice-chart version: 1.21.0 diff --git a/helm/values-dev.yaml b/helm/values-dev.yaml index fe774a6..ebc1c73 100644 --- a/helm/values-dev.yaml +++ b/helm/values-dev.yaml @@ -4,7 +4,7 @@ microservice-chart: fullnameOverride: "" image: repository: ghcr.io/pagopa/pagopa-mocker - tag: "1.0.2" + tag: "1.0.2-1-infrastructure-optimization" pullPolicy: Always livenessProbe: httpGet: @@ -94,3 +94,4 @@ microservice-chart: deployment: image: tag: 1.0.2 + create: false diff --git a/helm/values-uat.yaml b/helm/values-uat.yaml index 1e5c996..468815b 100644 --- a/helm/values-uat.yaml +++ b/helm/values-uat.yaml @@ -4,7 +4,7 @@ microservice-chart: fullnameOverride: "" image: repository: ghcr.io/pagopa/pagopa-mocker - tag: "1.0.2" + tag: "1.0.2-1-infrastructure-optimization" pullPolicy: Always livenessProbe: httpGet: @@ -94,3 +94,4 @@ microservice-chart: deployment: image: tag: 1.0.2 + create: false diff --git a/pom.xml b/pom.xml index 2fb73ad..ad09f65 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ it.gov.pagopa mocker - 1.0.2 + 1.0.2-1-infrastructure-optimization pagopa-mocker An HTTP request analyzer for dynamically mocking responses From 08e510690783c34634110d141ae178f6731468a7 Mon Sep 17 00:00:00 2001 From: Andrea De Rinaldis Date: Mon, 9 Oct 2023 17:26:01 +0200 Subject: [PATCH 7/7] feat: added and updated pipelines with GH Action --- .../workflows/{anchore.yml => 00_anchore.yml} | 0 .github/workflows/01_add_patch_label.yml | 60 ++++++ .github/workflows/01_assignee.yml | 26 +++ .github/workflows/02_check_pr.yml | 113 +++++++++++ .github/workflows/03_code_review.yml | 46 +++++ ...lease_deploy.yml => 04_release_deploy.yml} | 106 +++++----- ....yml => 04h_deploy_with_github_runner.yml} | 3 +- ...ation_test.yml => 05_integration_test.yml} | 0 .github/workflows/check_pr.yml | 190 ------------------ .github/workflows/code_review.yml | 118 ----------- 10 files changed, 300 insertions(+), 362 deletions(-) rename .github/workflows/{anchore.yml => 00_anchore.yml} (100%) create mode 100644 .github/workflows/01_add_patch_label.yml create mode 100644 .github/workflows/01_assignee.yml create mode 100644 .github/workflows/02_check_pr.yml create mode 100644 .github/workflows/03_code_review.yml rename .github/workflows/{release_deploy.yml => 04_release_deploy.yml} (51%) rename .github/workflows/{deploy_with_github_runner.yml => 04h_deploy_with_github_runner.yml} (97%) rename .github/workflows/{integration_test.yml => 05_integration_test.yml} (100%) delete mode 100644 .github/workflows/check_pr.yml delete mode 100644 .github/workflows/code_review.yml diff --git a/.github/workflows/anchore.yml b/.github/workflows/00_anchore.yml similarity index 100% rename from .github/workflows/anchore.yml rename to .github/workflows/00_anchore.yml diff --git a/.github/workflows/01_add_patch_label.yml b/.github/workflows/01_add_patch_label.yml new file mode 100644 index 0000000..41e5a82 --- /dev/null +++ b/.github/workflows/01_add_patch_label.yml @@ -0,0 +1,60 @@ +name: Add PATCH default label + +# Controls when the workflow will run +on: + # Triggers the workflow on push or pull request events but only for the main branch + pull_request_target: + branches: + - main + types: [ opened, reopened ] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + add_patch_label: + runs-on: ubuntu-latest + name: Add default label + steps: + - name: Check user labels + id: check_user_labels + uses: actions/github-script@v6.3.3 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + var addPatch = "true"; + // retrieve label list + let labels = await github.rest.issues.listLabelsOnIssue({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo + }); + + // verify if user have already added IGNORE-FOR-RELEASE, then skip add PATCH + // note: GitHub labels are added in .identity/03_github_environment.tf as github_issue_label resource + if (labels.data.find(label => label.name === 'ignore-for-release')){ + addPatch = "false"; + } + return addPatch; + result-encoding: string + + - name: Add PATCH label + if: ${{ steps.check_user_labels.outputs.result == 'true' }} + uses: pagopa/github-actions-template/default-label@main + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + label: 'patch' + + - name: Add comment + if: ${{ steps.check_user_labels.outputs.result == 'true' }} + uses: actions/github-script@v6.3.3 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: 'The default action is to increase the `PATCH` number of `SEMVER`. Set `IGNORE-FOR-RELEASE` if you want to skip `SEMVER` bump. `BREAKING-CHANGE` and `NEW-RELEASE` must be run from GH Actions section manually.' + }); diff --git a/.github/workflows/01_assignee.yml b/.github/workflows/01_assignee.yml new file mode 100644 index 0000000..0611917 --- /dev/null +++ b/.github/workflows/01_assignee.yml @@ -0,0 +1,26 @@ +name: Auto Assign + +# Controls when the workflow will run +on: + # Triggers the workflow on push or pull request events but only for the main branch + pull_request_target: + branches: + - main + types: [ opened, reopened ] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + build: + # The type of runner that the job will run on + runs-on: ubuntu-latest + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + - name: Assign Me + # You may pin to the exact commit or the version. + uses: kentaro-m/auto-assign-action@v1.2.1 + with: + configuration-path: '.github/auto_assign.yml' diff --git a/.github/workflows/02_check_pr.yml b/.github/workflows/02_check_pr.yml new file mode 100644 index 0000000..5608117 --- /dev/null +++ b/.github/workflows/02_check_pr.yml @@ -0,0 +1,113 @@ +name: Check PR + +# Controls when the workflow will run +on: + pull_request: + branches: + - main + types: [ opened, synchronize, labeled, unlabeled, reopened, edited ] + + +permissions: + pull-requests: write + + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + + check_labels: + name: Check Required Labels + # The type of runner that the job will run on + runs-on: ubuntu-latest + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + - name: Verify PR Labels + if: ${{ !contains(github.event.pull_request.labels.*.name, 'patch') && !contains(github.event.pull_request.labels.*.name, 'ignore-for-release') }} + uses: actions/github-script@v6.3.3 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + var comments = await github.rest.issues.listComments({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo + }); + for (const comment of comments.data) { + if (comment.body.includes('This pull request does not contain a valid label')){ + github.rest.issues.deleteComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: comment.id + }) + } + } + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: 'This pull request does not contain a valid label. Please add one of the following labels: `[patch, ignore-for-release]`' + }) + core.setFailed('Missing required labels') + + + check_format: + name: Check Format + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Formatting + id: format + continue-on-error: true + uses: axel-op/googlejavaformat-action@v3 + with: + args: "--set-exit-if-changed" + + - uses: actions/github-script@v6.3.3 + if: steps.format.outcome != 'success' + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + console.log(context); + var comments = await github.rest.issues.listComments({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo + }); + for (const comment of comments.data) { + console.log(comment); + if (comment.body.includes('Comment this PR with')){ + github.rest.issues.deleteComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: comment.id + }) + } + } + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: 'Comment this PR with *update_code* to format the code. Consider to use pre-commit to format the code.' + }) + core.setFailed('Format your code.') + + + check_size: + runs-on: ubuntu-latest + name: Check Size + steps: + + - name: Dump GitHub context + run: echo $JSON + env: + JSON: ${{ toJSON(github) }} + + - name: Check PR Size + uses: pagopa/github-actions-template/check-pr-size@main + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + ignored_files: 'openapi.json' diff --git a/.github/workflows/03_code_review.yml b/.github/workflows/03_code_review.yml new file mode 100644 index 0000000..b61a944 --- /dev/null +++ b/.github/workflows/03_code_review.yml @@ -0,0 +1,46 @@ +name: Code Review + +# Controls when the workflow will run +on: + pull_request: + branches: + - main + types: + - opened + - synchronize + - reopened + push: + branches: + - main + + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +env: + PROJECT_KEY: pagopa_pagopa-mocker + + +permissions: + id-token: write + contents: read + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + code-review: + name: Code Review + # The type of runner that the job will run on + runs-on: ubuntu-latest + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + - name: Code Review + uses: pagopa/github-actions-template/maven-code-review@50aaf5cffa09d76b953e64a630bc9e0528a6d73b + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + sonar_token: ${{ secrets.SONAR_TOKEN }} + project_key: ${{env.PROJECT_KEY}} + coverage_exclusions: "**/config/*,**/*Mock*,**/models/**,**/entities/*" + cpd_exclusions: "**/models/**,**/entities/*" + java_distribution: "graalvm" + java_version: "17.0.7" diff --git a/.github/workflows/release_deploy.yml b/.github/workflows/04_release_deploy.yml similarity index 51% rename from .github/workflows/release_deploy.yml rename to .github/workflows/04_release_deploy.yml index f2e9eb9..c29f348 100644 --- a/.github/workflows/release_deploy.yml +++ b/.github/workflows/04_release_deploy.yml @@ -3,6 +3,8 @@ name: Release And Deploy # Controls when the workflow will run on: pull_request: + branches: + - main types: [ closed ] # Allows you to run this workflow manually from the Actions tab @@ -15,18 +17,28 @@ on: options: - dev - uat - - all - beta: + - prod + semver: required: false - type: boolean - description: deploy beta version on AKS - default: false - skip_release: - required: false - type: boolean - description: skip the release. Only deploy - default: false - + type: choice + description: Select the version + options: + - '' + - skip + - promote + - patch + - new_release + - breaking_change + + workflow_call: + inputs: + environment: + required: true + type: string + semver: + required: true + type: string + default: skip permissions: packages: write @@ -42,49 +54,20 @@ jobs: name: Setup runs-on: ubuntu-latest outputs: - semver: ${{ steps.get_semver.outputs.semver }} - environment: ${{ steps.get_env.outputs.environment }} + semver: ${{ steps.semver_setup.outputs.semver }} + environment: ${{ steps.semver_setup.outputs.environment }} steps: - - name: pull request rejected - if: github.event_name == 'pull_request' && github.event.action == 'closed' && github.event.pull_request.merged != true - run: | - echo "❌ PR was closed without a merge" - exit 1 - - # Set Semvar - - run: echo "SEMVER=patch" >> $GITHUB_ENV - - - if: ${{ (github.event.pull_request.merged && contains(github.event.pull_request.labels.*.name, 'breaking-change ')) }} - run: echo "SEMVER=major" >> $GITHUB_ENV - - - if: ${{ inputs.environment == 'uat' }} - run: echo "SEMVER=minor" >> $GITHUB_ENV - - - if: ${{ github.ref_name != 'main' }} - run: echo "SEMVER=buildNumber" >> $GITHUB_ENV - - - if: ${{ inputs.skip_release }} - run: echo "SEMVER=skip" >> $GITHUB_ENV - - - id: get_semver - name: Set Output - run: echo "semver=${{env.SEMVER}}" >> $GITHUB_OUTPUT - - # Set Environment - - run: echo "ENVIRNOMENT=${{ inputs.environment}}" >> $GITHUB_ENV - - - if: ${{ inputs.environment == null }} - run: echo "ENVIRNOMENT=dev" >> $GITHUB_ENV - - - id: get_env - name: Set Output - run: echo "environment=${{env.ENVIRNOMENT}}" >> $GITHUB_OUTPUT - + - name: Semver setup + id: semver_setup + uses: pagopa/github-actions-template/nodo5-semver-setup@89ce1bcaf0da44968cd4e72d297cc916df5a914d + with: + semver: ${{ inputs.semver }} release: + needs: [setup] name: Create a New Release runs-on: ubuntu-latest - needs: [setup] + if: ${{ needs.setup.outputs.semver != 'skip' }} outputs: version: ${{ steps.release.outputs.version }} steps: @@ -101,7 +84,7 @@ jobs: needs: [ setup, release ] name: Build and Push Docker Image runs-on: ubuntu-latest - if: ${{ inputs.semver != 'skip' }} + if: ${{ needs.setup.outputs.semver != 'skip' }} steps: - name: Build and Push id: semver @@ -117,9 +100,28 @@ jobs: if: ${{ always() && !contains(needs.*.result, 'failure') && !contains(needs.*.result, 'cancelled') }} strategy: matrix: - environment: [ dev, uat ] - uses: ./.github/workflows/deploy_with_github_runner.yml + environment: [ dev, uat, prod ] + uses: ./.github/workflows/04h_deploy_with_github_runner.yml with: environment: ${{ matrix.environment }} target: ${{ needs.setup.outputs.environment }} secrets: inherit + +# notify: +# name: Notify +# needs: [ setup, release, deploy_aks ] +# runs-on: ubuntu-latest +# if: always() +# steps: +# - name: Report Status +# if: always() +# uses: ravsamhq/notify-slack-action@v2 +# with: +# status: ${{ needs.deploy_aks.result }} +# token: ${{ secrets.GITHUB_TOKEN }} +# notification_title: 'New Release on ${{ needs.setup.outputs.environment }} for ${{ needs.release.outputs.version }} has {status_message}' +# message_format: '{emoji} <{run_url}|{workflow}> {status_message} in <{repo_url}|{repo}>' +# footer: 'Linked to <{workflow_url}| workflow file>' +# icon_success: ':white_check_mark:' +# env: +# SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} diff --git a/.github/workflows/deploy_with_github_runner.yml b/.github/workflows/04h_deploy_with_github_runner.yml similarity index 97% rename from .github/workflows/deploy_with_github_runner.yml rename to .github/workflows/04h_deploy_with_github_runner.yml index b98b88b..710a96d 100644 --- a/.github/workflows/deploy_with_github_runner.yml +++ b/.github/workflows/04h_deploy_with_github_runner.yml @@ -42,7 +42,6 @@ jobs: container_app_environment_name: ${{ vars.CONTAINER_APP_ENVIRONMENT_NAME }} resource_group_name: ${{ vars.CONTAINER_APP_ENVIRONMENT_RESOURCE_GROUP_NAME }} # RG of the runner pat_token: ${{ secrets.BOT_TOKEN_GITHUB }} - self_hosted_runner_image_tag: "v1.4.1" deploy: needs: [ create_runner ] @@ -59,7 +58,7 @@ jobs: subscription_id: ${{ secrets.SUBSCRIPTION_ID }} tenant_id: ${{ secrets.TENANT_ID }} env: ${{ inputs.environment }} - namespace: ${{ env.NAMESPACE }} + namespace: ${{ vars.NAMESPACE }} cluster_name: ${{ vars.CLUSTER_NAME }} resource_group: ${{ vars.CLUSTER_RESOURCE_GROUP }} app_name: ${{ env.APP_NAME }} diff --git a/.github/workflows/integration_test.yml b/.github/workflows/05_integration_test.yml similarity index 100% rename from .github/workflows/integration_test.yml rename to .github/workflows/05_integration_test.yml diff --git a/.github/workflows/check_pr.yml b/.github/workflows/check_pr.yml deleted file mode 100644 index 953df7e..0000000 --- a/.github/workflows/check_pr.yml +++ /dev/null @@ -1,190 +0,0 @@ -name: Check PR - -# Controls when the workflow will run -on: - pull_request: - branches: - - main - types: [ opened, synchronize, labeled, unlabeled, reopened, edited ] - - -permissions: - pull-requests: write - - -# A workflow run is made up of one or more jobs that can run sequentially or in parallel -jobs: - auto_assign: - name: Auto Assign - - # The type of runner that the job will run on - runs-on: ubuntu-latest - - # Steps represent a sequence of tasks that will be executed as part of the job - steps: - - name: Assign Me - # You may pin to the exact commit or the version. - uses: kentaro-m/auto-assign-action@v1.2.1 - with: - configuration-path: '.github/auto_assign.yml' - - check_format: - name: Check Format - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Formatting - id: format - continue-on-error: true - uses: axel-op/googlejavaformat-action@v3 - with: - args: "--set-exit-if-changed" - - - uses: actions/github-script@v6.3.3 - if: steps.format.outcome != 'success' - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - console.log(context); - var comments = await github.rest.issues.listComments({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo - }); - for (const comment of comments.data) { - console.log(comment); - if (comment.body.includes('Comment this PR with')){ - github.rest.issues.deleteComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - comment_id: comment.id - }) - } - } - github.rest.issues.createComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - body: 'Comment this PR with *update_code* to update `openapi.json` and format the code. Consider to use pre-commit to format the code.' - }) - core.setFailed('Format your code.') - - check_size: - runs-on: ubuntu-latest - name: Check Size - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - - name: Check Size - uses: actions/github-script@v6.3.3 - env: - IGNORED_FILES: openapi.json, openapi-node.json - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - const additions = context.payload.pull_request.additions || 0 - const deletions = context.payload.pull_request.deletions || 0 - var changes = additions + deletions - console.log('additions: '+additions+' + deletions: '+deletions+ ' = total changes: ' + changes); - - const { IGNORED_FILES } = process.env - const ignored_files = IGNORED_FILES.trim().split(',').filter(word => word.length > 0); - if (ignored_files.length > 0){ - var ignored = 0 - const execSync = require('child_process').execSync; - for (const file of IGNORED_FILES.trim().split(',')) { - - const ignored_additions_str = execSync('git --no-pager diff --numstat origin/main..origin/${{ github.head_ref}} | grep ' + file + ' | cut -f 1', { encoding: 'utf-8' }) - const ignored_deletions_str = execSync('git --no-pager diff --numstat origin/main..origin/${{ github.head_ref}} | grep ' + file + ' | cut -f 2', { encoding: 'utf-8' }) - - const ignored_additions = ignored_additions_str.split('\n').map(elem=> parseInt(elem || 0)).reduce( - (accumulator, currentValue) => accumulator + currentValue, - 0); - const ignored_deletions = ignored_deletions_str.split('\n').map(elem=> parseInt(elem || 0)).reduce( - (accumulator, currentValue) => accumulator + currentValue, - 0); - - ignored += ignored_additions + ignored_deletions; - } - changes -= ignored - console.log('ignored lines: ' + ignored + ' , consider changes: ' + changes); - } - - if (changes < 200){ - github.rest.issues.addLabels({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - labels: ['size/small'] - }) - - - var labels = await github.rest.issues.listLabelsOnIssue({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo - }); - - if (labels.data.find(label => label.name == 'size/large')){ - github.rest.issues.removeLabel({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - name: 'size/large' - }) - } - } - - if (changes > 400){ - github.rest.issues.addLabels({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - labels: ['size/large'] - }) - - var comments = await github.rest.issues.listComments({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo - }); - for (const comment of comments.data) { - if (comment.body.includes('This PR exceeds the recommended size')){ - github.rest.issues.deleteComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - comment_id: comment.id - }) - } - } - - github.rest.issues.createComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - body: 'This PR exceeds the recommended size of 400 lines. Please make sure you are NOT addressing multiple issues with one PR. _Note this PR might be rejected due to its size._' - }) - - var labels = await github.rest.issues.listLabelsOnIssue({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo - }); - - if (labels.data.find(label => label.name == 'size/small')){ - github.rest.issues.removeLabel({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - name: 'size/small' - }) - } - - } - diff --git a/.github/workflows/code_review.yml b/.github/workflows/code_review.yml deleted file mode 100644 index a04c95c..0000000 --- a/.github/workflows/code_review.yml +++ /dev/null @@ -1,118 +0,0 @@ -name: Code Review - -# Controls when the workflow will run -on: - pull_request: - branches: - - main - types: - - opened - - synchronize - - reopened - push: - branches: - - main - - - # Allows you to run this workflow manually from the Actions tab - workflow_dispatch: - -env: - PROJECT_KEY: pagopa_pagopa-mocker - -permissions: - id-token: write - contents: read - deployments: write - -# A workflow run is made up of one or more jobs that can run sequentially or in parallel -jobs: - code-review: - name: Code Review - # The type of runner that the job will run on - runs-on: ubuntu-latest - - # Steps represent a sequence of tasks that will be executed as part of the job - steps: - - name: Code Review - uses: pagopa/github-actions-template/maven-code-review@v1.4.2 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - sonar_token: ${{ secrets.SONAR_TOKEN }} - project_key: ${{env.PROJECT_KEY}} - coverage_exclusions: "**/config/*,**/controller/*,**/model/**,**/entity/*" - cpd_exclusions: "**/model/**,**/entity/*" - - smoke-test: - name: Smoke Test - runs-on: ubuntu-latest - environment: - name: dev - steps: - - name: Checkout - id: checkout - uses: actions/checkout@1f9a0c22da41e6ebfa534300ef656657ea2c6707 - - - name: Login - id: login - # from https://github.com/Azure/login/commits/master - uses: azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 - with: - client-id: ${{ secrets.CLIENT_ID }} - tenant-id: ${{ secrets.TENANT_ID }} - subscription-id: ${{ secrets.SUBSCRIPTION_ID }} - - - name: Run Service on Docker - shell: bash - id: run_service_docker - run: | - cd ./docker - chmod +x ./run_docker.sh - ./run_docker.sh local - - - name: Run Integration Tests - shell: bash - id: run_integration_test - run: | - export SUBKEY=${{ secrets.SUBKEY }} - export CANARY=${{ inputs.canary }} - export CUCUMBER_PUBLISH_TOKEN=${{ secrets.CUCUMBER_PUBLISH_TOKEN }} - - cd ./integration-test - chmod +x ./run_integration_test.sh - ./run_integration_test.sh local - - - delete_github_deployments: - runs-on: ubuntu-latest - needs: smoke-test - if: ${{ always() }} - steps: - - name: Delete Previous deployments - uses: actions/github-script@v6 - env: - SHA_HEAD: ${{ (github.event_name == 'pull_request' && github.event.pull_request.head.sha) || github.sha}} - with: - script: | - const { SHA_HEAD } = process.env - - const deployments = await github.rest.repos.listDeployments({ - owner: context.repo.owner, - repo: context.repo.repo, - sha: SHA_HEAD - }); - await Promise.all( - deployments.data.map(async (deployment) => { - await github.rest.repos.createDeploymentStatus({ - owner: context.repo.owner, - repo: context.repo.repo, - deployment_id: deployment.id, - state: 'inactive' - }); - return github.rest.repos.deleteDeployment({ - owner: context.repo.owner, - repo: context.repo.repo, - deployment_id: deployment.id - }); - }) - );