diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json new file mode 100644 index 00000000..8c5c7ef8 --- /dev/null +++ b/.config/dotnet-tools.json @@ -0,0 +1,10 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "csharpier": { + "version": "0.25.0", + "commands": ["dotnet-csharpier"] + } + } +} diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index f6562ee3..35972116 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -126,7 +126,8 @@ jobs: - build permissions: actions: read - id-token: write # for creating OIDC tokens for signing. + # for creating OIDC tokens for signing. + id-token: write packages: write # for uploading attestations. if: ${{ startsWith(github.ref, 'refs/tags/') }} uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v1.6.0 diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index e9e83942..c537a7c5 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -19,7 +19,8 @@ jobs: permissions: actions: read contents: read - id-token: write # for creating OIDC tokens for signing. + # for creating OIDC tokens for signing. + id-token: write packages: write # for uploading container images, signatures, and attestations. strategy: matrix: @@ -84,7 +85,8 @@ jobs: permissions: actions: read contents: write # for release notes - id-token: write # for creating OIDC tokens for signing. + # for creating OIDC tokens for signing. + id-token: write packages: write # for uploading container images, signatures, and attestations. needs: - k8s-test diff --git a/.github/workflows/mega-linter.yml b/.github/workflows/mega-linter.yml index 8fca5073..4fa52c2e 100644 --- a/.github/workflows/mega-linter.yml +++ b/.github/workflows/mega-linter.yml @@ -4,9 +4,11 @@ name: MegaLinter on: + # Trigger mega-linter at every push. Action will also be visible from Pull Requests to master pull_request: - branches: - - master + branches: [master] + +permissions: read-all env: # Comment env block if you do not want to apply fixes # Apply linter fixes configuration @@ -18,28 +20,27 @@ concurrency: group: ${{ github.ref }}-${{ github.workflow }} cancel-in-progress: true -permissions: read-all - jobs: build: name: MegaLinter runs-on: ubuntu-22.04 permissions: + contents: read pull-requests: write steps: # Git Checkout - name: Checkout Code - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3 + uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 with: token: ${{ secrets.GITHUB_TOKEN }} - fetch-depth: 0 + fetch-depth: 0 # If you use VALIDATE_ALL_CODEBASE = true, you can remove this line to improve performances # MegaLinter - name: MegaLinter id: ml # You can override MegaLinter flavor used to have faster performances # More info at https://oxsecurity.github.io/megalinter/flavors/ - uses: oxsecurity/megalinter@93700f8c21c59ea784a32abe23896e49e54463b8 # v6.22.2 + uses: oxsecurity/megalinter@a87b2872713c6bdde46d2473c5d7ed23e5752dc2 # v7.4.0 env: # All available variables are described in documentation # https://oxsecurity.github.io/megalinter/configuration/ @@ -49,8 +50,8 @@ jobs: # Upload MegaLinter artifacts - name: Archive production artifacts - if: ${{ success() }} || ${{ failure() }} - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3 + if: ${{ always() }} + uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 with: name: MegaLinter reports path: | diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 17899d83..2c51197f 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -170,7 +170,8 @@ jobs: - prepare-artifacts permissions: actions: read # To read the workflow path. - id-token: write # To sign the provenance. + # To sign the provenance. + id-token: write contents: write # To add assets to a release. # can't be referenced by digest. See uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.6.0 diff --git a/.github/workflows/test-compose-installation.yaml b/.github/workflows/test-compose-installation.yaml index 3da73b62..c47e5524 100644 --- a/.github/workflows/test-compose-installation.yaml +++ b/.github/workflows/test-compose-installation.yaml @@ -34,6 +34,13 @@ jobs: docker load --input /tmp/notify-build-artifacts/notify-image.tar docker image ls -a + - name: Delete downloaded artifacts + run: | + df -h + rm -rf /tmp/*-build-artifacts + rm -rf /tmp/*-attestations + df -h + - name: Deploy using Docker Compose in staging mode run: | docker compose \ diff --git a/.github/workflows/test-k8s-installation.yaml b/.github/workflows/test-k8s-installation.yaml index 428fae4c..63a60601 100644 --- a/.github/workflows/test-k8s-installation.yaml +++ b/.github/workflows/test-k8s-installation.yaml @@ -16,6 +16,15 @@ jobs: steps: - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + - name: downgrade helm + shell: bash + run: | + rm /usr/local/bin/helm + curl -fsSL https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 > /tmp/helm.sh + chmod +x /tmp/helm.sh + /tmp/helm.sh --version v3.12.3 + helm version + - name: Set up Docker Buildx uses: docker/setup-buildx-action@4b4e9c3e2d4531116a6f8ba8e71fc6e2cb6e6c8c # v2.5.0 diff --git a/.kics.yaml b/.kics.yaml new file mode 100644 index 00000000..5cb00982 --- /dev/null +++ b/.kics.yaml @@ -0,0 +1,6 @@ +exclude-paths: + - "tests/" + - "docs/" + - "src/hack" + - "charts/recruit/docs" + - "charts/recruit/values.yaml" diff --git a/.mega-linter.yml b/.mega-linter.yml index 0e65cc87..5546cebc 100644 --- a/.mega-linter.yml +++ b/.mega-linter.yml @@ -23,6 +23,7 @@ DISABLE_LINTERS: - YAML_V8R # seems to ignore yamllint config file entirely - YAML_YAMLLINT + - SPELL_LYCHEE SHOW_ELAPSED_TIME: true FILEIO_REPORTER: false @@ -44,3 +45,11 @@ JAVA_CHECKSTYLE_CONFIG_FILE: src/config/checkstyle/checkstyle.xml REPOSITORY_TRIVY_ARGUMENTS: - "--severity=HIGH,CRITICAL" - "--ignore-unfixed" + +REPOSITORY_CHECKOV_ARGUMENTS: + - "--skip-path=tests/" + +REPOSITORY_KICS_ARGUMENTS: + - --fail-on=HIGH + +REPOSITORY_KICS_CONFIG_FILE: .kics.yaml diff --git a/.polaris.yaml b/.polaris.yaml index 0419dbda..37195b4b 100644 --- a/.polaris.yaml +++ b/.polaris.yaml @@ -18,6 +18,7 @@ checks: memoryLimitsMissing: ignore # security + # kics-scan ignore-line automountServiceAccountToken: ignore hostIPCSet: danger hostPIDSet: danger diff --git a/charts/recruit/ci/kitchen-sink-values.yaml b/charts/recruit/ci/kitchen-sink-values.yaml index 536003f4..81c625fa 100644 --- a/charts/recruit/ci/kitchen-sink-values.yaml +++ b/charts/recruit/ci/kitchen-sink-values.yaml @@ -73,6 +73,7 @@ query: postgresql: enabled: true auth: + # kics-scan ignore-line postgresPassword: recruit-notify-ha primary: service: @@ -86,6 +87,7 @@ ohdsi: - host: recruit-ohdsi.127.0.0.1.nip.io postgresql: auth: + # kics-scan ignore-line postgresPassword: ohdsi primary: service: @@ -132,6 +134,7 @@ fhirserver: paths: ["/"] postgresql: auth: + # kics-scan ignore-line postgresPassword: fhir primary: service: diff --git a/charts/recruit/values-integrationtest.yaml b/charts/recruit/values-integrationtest.yaml index 6962c2e0..8fa22897 100644 --- a/charts/recruit/values-integrationtest.yaml +++ b/charts/recruit/values-integrationtest.yaml @@ -1,6 +1,7 @@ fhirserver: postgresql: auth: + # kics-scan ignore-line postgresPassword: fhir query: @@ -13,6 +14,7 @@ query: port: 5432 database: postgres username: postgres + # kics-scan ignore-line password: mypass resultsSchema: demo_cdm_results cdmSchema: demo_cdm @@ -47,6 +49,7 @@ notify: postgresql: enabled: true auth: + # kics-scan ignore-line postgresPassword: recruit-notify-ha ohdsi: @@ -58,6 +61,7 @@ ohdsi: port: 5432 database: "postgres" username: "postgres" + # kics-scan ignore-line password: "mypass" schema: "webapi" extraEnv: diff --git a/charts/recruit/values-test.yaml b/charts/recruit/values-test.yaml index efee8751..b5926cd6 100644 --- a/charts/recruit/values-test.yaml +++ b/charts/recruit/values-test.yaml @@ -1,6 +1,7 @@ ohdsi: postgresql: auth: + # kics-scan ignore-line postgresPassword: ohdsi primary: service: @@ -17,6 +18,7 @@ ohdsi: fhirserver: postgresql: auth: + # kics-scan ignore-line postgresPassword: fhir primary: service: @@ -73,6 +75,7 @@ notify: postgresql: enabled: true auth: + # kics-scan ignore-line postgresPassword: recruit-notify-ha primary: service: diff --git a/docker-compose/docker-compose.staging.yaml b/docker-compose/docker-compose.staging.yaml index 8a6a7094..c6333ebc 100644 --- a/docker-compose/docker-compose.staging.yaml +++ b/docker-compose/docker-compose.staging.yaml @@ -15,6 +15,7 @@ services: ports: - "127.0.0.1:80:80" volumes: + # kics-scan ignore-line - "/var/run/docker.sock:/var/run/docker.sock:ro" deploy: resources: @@ -54,6 +55,7 @@ services: DATASOURCE_DRIVERCLASSNAME: org.postgresql.Driver DATASOURCE_URL: jdbc:postgresql://omopdb:5432/ohdsi DATASOURCE_USERNAME: postgres + # kics-scan ignore-line DATASOURCE_PASSWORD: postgres DATASOURCE_OHDSI_SCHEMA: ohdsi SPRING_JPA_PROPERTIES_HIBERNATE_DIALECT: org.hibernate.dialect.PostgreSQLDialect @@ -62,6 +64,7 @@ services: FLYWAY_DATASOURCE_DRIVERCLASSNAME: org.postgresql.Driver FLYWAY_DATASOURCE_URL: jdbc:postgresql://omopdb:5432/ohdsi FLYWAY_DATASOURCE_USERNAME: postgres + # kics-scan ignore-line FLYWAY_DATASOURCE_PASSWORD: postgres FLYWAY_LOCATIONS: classpath:db/migration/postgresql FLYWAY_PLACEHOLDERS_OHDSISCHEMA: ohdsi @@ -118,6 +121,7 @@ services: environment: SPRING_DATASOURCE_URL: "jdbc:postgresql://fhir-db:5432/fhir?currentSchema=public" SPRING_DATASOURCE_USERNAME: postgres + # kics-scan ignore-line SPRING_DATASOURCE_PASSWORD: postgres SPRING_DATASOURCE_DRIVERCLASSNAME: org.postgresql.Driver spring.jpa.properties.hibernate.dialect: ca.uhn.fhir.jpa.model.dialect.HapiFhirPostgres94Dialect @@ -147,6 +151,7 @@ services: - "no-new-privileges:true" privileged: false environment: + # kics-scan ignore-line POSTGRES_PASSWORD: postgres POSTGRES_DB: fhir @@ -191,6 +196,7 @@ services: privileged: false environment: KEYCLOAK_USER: admin + # kics-scan ignore-line KEYCLOAK_PASSWORD: admin KEYCLOAK_STATISTICS: "all" volumes: diff --git a/docker-compose/docker-compose.yaml b/docker-compose/docker-compose.yaml index cccec00b..0f73af88 100644 --- a/docker-compose/docker-compose.yaml +++ b/docker-compose/docker-compose.yaml @@ -45,6 +45,7 @@ services: FHIR_URL: ${FHIR_URL:?} OMOP_JDBCURL: ${OMOP_JDBCURL:?} OMOP_USERNAME: ${OMOP_USERNAME:?} + # kics-scan ignore-line OMOP_PASSWORD: ${OMOP_PASSWORD:?} OMOP_RESULTSSCHEMA: ${OMOP_RESULTSSCHEMA:?} OMOP_CDMSCHEMA: ${OMOP_CDMSCHEMA:?} @@ -86,6 +87,7 @@ services: SPRING_MAIL_HOST: ${NOTIFY_MAIL_HOST:?} SPRING_MAIL_PORT: ${NOTIFY_MAIL_SMTP_PORT:?} SPRING_MAIL_USERNAME: ${NOTIFY_MAIL_USERNAME} + # kics-scan ignore-line SPRING_MAIL_PASSWORD: ${NOTIFY_MAIL_PASSWORD} volumes: - type: tmpfs diff --git a/src/hack/docker-compose.yaml b/src/hack/docker-compose.yaml index d731dc96..fad76d06 100644 --- a/src/hack/docker-compose.yaml +++ b/src/hack/docker-compose.yaml @@ -15,6 +15,7 @@ services: ports: - "127.0.0.1:80:80" volumes: + # kics-scan ignore-line - "/var/run/docker.sock:/var/run/docker.sock:ro" deploy: resources: diff --git a/src/list/frontend/deploy/docker-compose.dev.yml b/src/list/frontend/deploy/docker-compose.dev.yml index ad9759c7..70cfed0b 100644 --- a/src/list/frontend/deploy/docker-compose.dev.yml +++ b/src/list/frontend/deploy/docker-compose.dev.yml @@ -43,6 +43,7 @@ services: - -Dkeycloak.migration.file=/tmp/realm.json environment: KEYCLOAK_USER: admin + # kics-scan ignore-line KEYCLOAK_PASSWORD: admin volumes: - ./data/aio-export.json:/tmp/realm.json diff --git a/src/list/frontend/deploy/staging/values.yaml b/src/list/frontend/deploy/staging/values.yaml deleted file mode 100644 index 072534dd..00000000 --- a/src/list/frontend/deploy/staging/values.yaml +++ /dev/null @@ -1,31 +0,0 @@ -deploymentAnnotations: - app.gitlab.com/app: miracum-uc1-recruit-list - app.gitlab.com/env: staging -podAnnotations: - app.gitlab.com/app: miracum-uc1-recruit-list - app.gitlab.com/env: staging -ohdsi: - enabled: false -query: - enabled: false -notify: - enabled: false -mailhog: - enabled: false -fhirserver: - postgresql: - postgresqlPassword: "fhir-server-postgres-password" -list: - ingress: - enabled: true - annotations: - cert-manager.io/cluster-issuer: letsencrypt-prod - kubernetes.io/ingress.class: nginx - hosts: - - host: lists.recruit.miracum.org - paths: - - "/" - tls: - - secretName: lists.recruit.miracum.org-tls - hosts: - - lists.recruit.miracum.org diff --git a/src/list/frontend/tests/e2e/docker-compose.yaml b/src/list/frontend/tests/e2e/docker-compose.yaml index 2e91536e..a6ddc08d 100644 --- a/src/list/frontend/tests/e2e/docker-compose.yaml +++ b/src/list/frontend/tests/e2e/docker-compose.yaml @@ -64,6 +64,7 @@ services: - -Dkeycloak.migration.file=/tmp/realm.json environment: KEYCLOAK_USER: admin + # kics-scan ignore-line KEYCLOAK_PASSWORD: admin volumes: - ${PWD}/frontend/deploy/data/aio-export.json:/tmp/realm.json:ro diff --git a/src/notify/src/main/resources/application-dev.yml b/src/notify/src/main/resources/application-dev.yml index ed55347f..f4605d56 100644 --- a/src/notify/src/main/resources/application-dev.yml +++ b/src/notify/src/main/resources/application-dev.yml @@ -40,11 +40,13 @@ spring: datasource: url: "jdbc:postgresql://localhost:6432/recruit_notify_jobs?ApplicationName=recruit-notify" username: "postgres" + # kics-scan ignore-line password: "postgres" # pragma: allowlist secret mail: host: localhost port: 3025 username: noreply@test.de + # kics-scan ignore-line password: "" properties: mail: diff --git a/src/notify/tests/e2e/docker-compose.yaml b/src/notify/tests/e2e/docker-compose.yaml index 781c4e34..e14911c1 100644 --- a/src/notify/tests/e2e/docker-compose.yaml +++ b/src/notify/tests/e2e/docker-compose.yaml @@ -10,9 +10,11 @@ services: SPRING_MAIL_HOST: maildev SPRING_MAIL_PORT: 1025 SPRING_MAIL_USERNAME: maildev + # kics-scan ignore-line SPRING_MAIL_PASSWORD: maildev # pragma: allowlist secret SPRING_PROFILES_ACTIVE: ${SPRING_PROFILES_ACTIVE:-prod} SPRING_DATASOURCE_USERNAME: postgres + # kics-scan ignore-line SPRING_DATASOURCE_PASSWORD: postgres # pragma: allowlist secret SPRING_DATASOURCE_URL: jdbc:postgresql://jobstore-db:5432/recruit_notify_jobs?ApplicationName=recruit-notify volumes: @@ -24,6 +26,7 @@ services: jobstore-db: image: docker.io/library/postgres:14.5@sha256:f8816ada742348e1adfcec5c2a180b675bf6e4a294e0feb68bd70179451e1242 environment: + # kics-scan ignore-line POSTGRES_PASSWORD: postgres # pragma: allowlist secret POSTGRES_DB: recruit_notify_jobs diff --git a/src/query/src/main/resources/application-dev.yml b/src/query/src/main/resources/application-dev.yml index 7e7f4c14..5b58c126 100644 --- a/src/query/src/main/resources/application-dev.yml +++ b/src/query/src/main/resources/application-dev.yml @@ -1,6 +1,7 @@ omop: jdbcUrl: "jdbc:postgresql://localhost:25432/postgres" username: "postgres" + # kics-scan ignore-line password: "mypass" resultsSchema: "demo_cdm_results" cdmSchema: "demo_cdm" @@ -15,6 +16,7 @@ query: enabled: false login-path: "/user/login/db" username: "recruit-query-module" + # kics-scan ignore-line password: "pass123" cohort-cache: schema: webapi diff --git a/src/query/tests/e2e/docker-compose.yaml b/src/query/tests/e2e/docker-compose.yaml index 676722dc..882e8689 100644 --- a/src/query/tests/e2e/docker-compose.yaml +++ b/src/query/tests/e2e/docker-compose.yaml @@ -6,6 +6,7 @@ services: FHIR_URL: http://fhir:8080/fhir OMOP_JDBCURL: jdbc:postgresql://broadsea-atlasdb:5432/postgres OMOP_USERNAME: postgres + # kics-scan ignore-line OMOP_PASSWORD: mypass OMOP_RESULTSSCHEMA: demo_cdm_results OMOP_CDMSCHEMA: demo_cdm @@ -15,6 +16,7 @@ services: QUERY_WEBAPI_AUTH_ENABLED: "false" # TODO: re-enable when atlasdb supports/has been augmented with auth support. QUERY_WEBAPI_AUTH_LOGIN_PATH: "/user/login/db" QUERY_WEBAPI_AUTH_USERNAME: "recruit-query-module" + # kics-scan ignore-line QUERY_WEBAPI_AUTH_PASSWORD: "pass123" QUERY_WEBAPI_COHORT_CACHE_SCHEMA: "webapi" QUERY_SELECTOR_MATCHLABELS: "" @@ -59,6 +61,7 @@ services: DATASOURCE_DRIVERCLASSNAME: org.postgresql.Driver DATASOURCE_URL: jdbc:postgresql://broadsea-atlasdb:5432/postgres DATASOURCE_USERNAME: postgres + # kics-scan ignore-line DATASOURCE_PASSWORD: mypass DATASOURCE_OHDSI_SCHEMA: webapi SPRING_JPA_PROPERTIES_HIBERNATE_DIALECT: org.hibernate.dialect.PostgreSQLDialect @@ -67,6 +70,7 @@ services: FLYWAY_DATASOURCE_DRIVERCLASSNAME: org.postgresql.Driver FLYWAY_DATASOURCE_URL: jdbc:postgresql://broadsea-atlasdb:5432/postgres FLYWAY_DATASOURCE_USERNAME: postgres + # kics-scan ignore-line FLYWAY_DATASOURCE_PASSWORD: mypass FLYWAY_LOCATIONS: classpath:db/migration/postgresql FLYWAY_PLACEHOLDERS_OHDSISCHEMA: webapi @@ -78,12 +82,13 @@ services: SECURITY_CORS_ENABLED: "true" SECURITY_ORIGIN: "*" # SECURITY_PROVIDER: "AtlasRegularSecurity" - # SECURITY_DB_DATASOURCE_URL: jdbc:postgresql://broadsea-atlasdb:5432/postgres - # SECURITY_DB_DATASOURCE_DRIVERCLASSNAME: org.postgresql.Driver - # SECURITY_DB_DATASOURCE_SCHEMA: webapi - # SECURITY_DB_DATASOURCE_USERNAME: postgres - # SECURITY_DB_DATASOURCE_PASSWORD: mypass - # SECURITY_DB_DATASOURCE_AUTHENTICATIONQUERY: >- - # SELECT password, first_name AS firstname, middle_name AS middlename, last_name AS lastname, username FROM webapi.basic_security_users WHERE username = ? + SECURITY_DB_DATASOURCE_URL: jdbc:postgresql://broadsea-atlasdb:5432/postgres + SECURITY_DB_DATASOURCE_DRIVERCLASSNAME: org.postgresql.Driver + SECURITY_DB_DATASOURCE_SCHEMA: webapi + SECURITY_DB_DATASOURCE_USERNAME: postgres + # kics-scan ignore-line + SECURITY_DB_DATASOURCE_PASSWORD: mypass + SECURITY_DB_DATASOURCE_AUTHENTICATIONQUERY: >- + SELECT password, first_name AS firstname, middle_name AS middlename, last_name AS lastname, username FROM webapi.basic_security_users WHERE username = ? depends_on: - broadsea-atlasdb diff --git a/src/skaffold.yaml b/src/skaffold.yaml index 9b717d17..1690bdff 100644 --- a/src/skaffold.yaml +++ b/src/skaffold.yaml @@ -30,7 +30,9 @@ manifests: chartPath: ../charts/recruit skipBuildDependencies: true setValues: + # kics-scan ignore-line fhirserver.postgresql.auth.postgresPassword: fhir + # kics-scan ignore-line ohdsi.postgresql.auth.postgresPassword: ohdsi wait: true flags: @@ -43,7 +45,9 @@ deploy: chartPath: helm skipBuildDependencies: true setValues: + # kics-scan ignore-line fhirserver.postgresql.auth.postgresPassword: fhir + # kics-scan ignore-line ohdsi.postgresql.auth.postgresPassword: ohdsi flags: install: diff --git a/tests/chaos/tester/Program.cs b/tests/chaos/tester/Program.cs index 51872173..9869fb68 100644 --- a/tests/chaos/tester/Program.cs +++ b/tests/chaos/tester/Program.cs @@ -24,20 +24,23 @@ // test command var fileOption = new Option( - name: "--fhir-resource-bundle", - description: "The file containing the bundle of resources to send to the FHIR server.") + name: "--fhir-resource-bundle", + description: "The file containing the bundle of resources to send to the FHIR server." +) { IsRequired = true, }; var sendCountOption = new Option( - name: "--send-count", - description: "The number of times the bundle should be sent to to FHIR server."); + name: "--send-count", + description: "The number of times the bundle should be sent to to FHIR server." +); sendCountOption.SetDefaultValue(5); var fhirServerUrlOption = new Option( - name: "--fhir-server-base-url", - description: "The base URL of the FHIR server."); + name: "--fhir-server-base-url", + description: "The base URL of the FHIR server." +); fhirServerUrlOption.SetDefaultValue(new Uri("http://localhost:8082/fhir")); var durationOption = new Option( @@ -46,26 +49,37 @@ ); durationOption.SetDefaultValue(TimeSpan.FromSeconds(30)); -var testCommand = new Command("test", "Run the test by submitting the FHIR resource bundle to the server.") +var testCommand = new Command( + "test", + "Run the test by submitting the FHIR resource bundle to the server." +) { fileOption, fhirServerUrlOption, durationOption, sendCountOption, }; -testCommand.SetHandler((file, fhirServerUrl, totalDuration, sendCount) => RunTest(file!, fhirServerUrl, totalDuration, sendCount), - fileOption, fhirServerUrlOption, durationOption, sendCountOption); +testCommand.SetHandler( + (file, fhirServerUrl, totalDuration, sendCount) => + RunTest(file!, fhirServerUrl, totalDuration, sendCount), + fileOption, + fhirServerUrlOption, + durationOption, + sendCountOption +); rootCommand.AddCommand(testCommand); // assert command var expectedMessageCountOption = new Option( - name: "--expected-number-of-messages", - description: "The expected number of messages."); + name: "--expected-number-of-messages", + description: "The expected number of messages." +); expectedMessageCountOption.SetDefaultValue(5); var retriesOption = new Option( - name: "--retries", - description: "The number of times to re-assert the number of messages present compared to the expected"); + name: "--retries", + description: "The number of times to re-assert the number of messages present compared to the expected" +); retriesOption.SetDefaultValue(10); var assertCommand = new Command("assert", "Verify that the expected number of mails were received.") @@ -74,15 +88,27 @@ expectedMessageCountOption, retriesOption, }; -assertCommand.SetHandler(RunAssert, mailHogApiBaseUrlOption, expectedMessageCountOption, retriesOption); +assertCommand.SetHandler( + RunAssert, + mailHogApiBaseUrlOption, + expectedMessageCountOption, + retriesOption +); rootCommand.AddCommand(assertCommand); return await rootCommand.InvokeAsync(args); -static async System.Threading.Tasks.Task RunTest(FileInfo fhirResourceBundle, Uri fhirServerUrl, TimeSpan totalDuration, int sendCount) +static async System.Threading.Tasks.Task RunTest( + FileInfo fhirResourceBundle, + Uri fhirServerUrl, + TimeSpan totalDuration, + int sendCount +) { - Console.WriteLine($"Sending FHIR bundle from file {fhirResourceBundle.FullName} " + - $"to server {fhirServerUrl} {sendCount} times over a duration of {totalDuration} ({totalDuration.TotalSeconds}s)"); + Console.WriteLine( + $"Sending FHIR bundle from file {fhirResourceBundle.FullName} " + + $"to server {fhirServerUrl} {sendCount} times over a duration of {totalDuration} ({totalDuration.TotalSeconds}s)" + ); var fhirSerializerOptions = new JsonSerializerOptions().ForFhir(typeof(Bundle).Assembly); @@ -99,11 +125,14 @@ static async System.Threading.Tasks.Task RunTest(FileInfo fhirResourceBundle, Ur var policy = Policy .Handle() - .WaitAndRetry(3, retryAttempt => - { - Console.WriteLine($"Failed to send the bundle. Attempt: {retryAttempt}"); - return TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)); - }); + .WaitAndRetry( + 3, + retryAttempt => + { + Console.WriteLine($"Failed to send the bundle. Attempt: {retryAttempt}"); + return TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)); + } + ); var response = policy.Execute(() => client.Transaction(bundle)); @@ -116,13 +145,11 @@ static async System.Threading.Tasks.Task RunDeleteMessages(Uri mailHogServerBase { Console.WriteLine("Deleting all previous messages"); - var mailHogClient = new HttpClient - { - BaseAddress = mailHogServerBaseUrl, - }; + var mailHogClient = new HttpClient { BaseAddress = mailHogServerBaseUrl, }; - var messagesResponse = await mailHogClient.GetFromJsonAsync("v2/messages") ?? - throw new Exception("Getting messages from MailHog failed"); + var messagesResponse = + await mailHogClient.GetFromJsonAsync("v2/messages") + ?? throw new Exception("Getting messages from MailHog failed"); Console.WriteLine($"A total of {messagesResponse.Total} messages already on the server."); @@ -132,26 +159,30 @@ static async System.Threading.Tasks.Task RunDeleteMessages(Uri mailHogServerBase Console.WriteLine("Done."); } -static async System.Threading.Tasks.Task RunAssert(Uri mailHogServerBaseUrl, int expectedMessageCount, int retries) +static async System.Threading.Tasks.Task RunAssert( + Uri mailHogServerBaseUrl, + int expectedMessageCount, + int retries +) { Console.WriteLine($"Using MailHog base URL: {mailHogServerBaseUrl}"); - var client = new HttpClient - { - BaseAddress = mailHogServerBaseUrl, - }; + var client = new HttpClient { BaseAddress = mailHogServerBaseUrl, }; for (int i = 0; i < retries; i++) { MailHogMessages response; try { - response = await client.GetFromJsonAsync("v2/messages") ?? - throw new Exception("Getting messages from MailHog failed"); + response = + await client.GetFromJsonAsync("v2/messages") + ?? throw new Exception("Getting messages from MailHog failed"); } catch (Exception exc) { - Console.WriteLine($"Failed to get response from MailHog: {exc.Message}. Attempt: {i + 1}"); + Console.WriteLine( + $"Failed to get response from MailHog: {exc.Message}. Attempt: {i + 1}" + ); if (i == retries - 1) { throw; @@ -161,7 +192,9 @@ static async System.Threading.Tasks.Task RunAssert(Uri mailHogServerBaseUrl, int continue; } - Console.WriteLine($"Expected message count is {expectedMessageCount}. Actual: {response.Total}. Attempt: {i + 1}"); + Console.WriteLine( + $"Expected message count is {expectedMessageCount}. Actual: {response.Total}. Attempt: {i + 1}" + ); if (expectedMessageCount == response.Total) { @@ -171,7 +204,9 @@ static async System.Threading.Tasks.Task RunAssert(Uri mailHogServerBaseUrl, int if (i == retries - 1) { - throw new Exception($"response.Total ({response.Total}) is not the expected {expectedMessageCount} after {i + 1} attempts."); + throw new Exception( + $"response.Total ({response.Total}) is not the expected {expectedMessageCount} after {i + 1} attempts." + ); } await System.Threading.Tasks.Task.Delay(TimeSpan.FromMinutes(1));