diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index cb7d5f1..74a33d0 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -20,8 +20,8 @@ } }, "containerEnv": { - "AUTH_API_ROOT_URL": "http://localhost:8504/api", - "API_ROOT_URL": "http://localhost:6504", + "AUTH_API_ROOT_URL": "http://localhost:8504/api/auth", + "API_ROOT_URL": "http://localhost:6504/api", "SHOULD_USE_FAKE_EXTERNAL_DEPENDENCIES": "true" } } \ No newline at end of file diff --git a/.dockerignore b/.dockerignore index 90c8f65..15056b7 100644 --- a/.dockerignore +++ b/.dockerignore @@ -23,4 +23,42 @@ **/values.dev.yaml LICENSE README.md -target/ \ No newline at end of file +!**/.gitignore +!.git/HEAD +!.git/config +!.git/packed-refs +!.git/refs/heads/** + +# we don't need tests and their related code in production +**/*Tests.cs +**/*TestsRelated.cs + +**/bin/* +**/obj/* +**/.vs/* +**/.vscode/* +**.user +**.http + +**/appsettings.** +# need to include these files for tests execution in docker compose even though these maigh not be used in prod +!**/appsettings.json +!**/appsettings.MockForPullRequest.json + +**/Dockerfile +**/lib/* + +.devcontainer/ +.github/ +target/ +ci/ +e2e/ + +.dockerignore +.editorconfig +.gitattributes +.gitignore +docker-compose.yml +LICENSE +pgAdmin.json +README.md \ No newline at end of file diff --git a/.github/workflows/.reusable-docker-build-and-push.yml b/.github/workflows/.reusable-docker-build-and-push.yml new file mode 100644 index 0000000..e2709a6 --- /dev/null +++ b/.github/workflows/.reusable-docker-build-and-push.yml @@ -0,0 +1,197 @@ +name: Publish Docker image + +# !!! NEVER add on push when there is on workflow_call +# if you do that the workflow can run multiple times +# for instance if you re-use this docker build workflow for prod deployment and for local-env in PR +# it will build the docker image it twice +# if you build => deploy => run e2e against prod it will build the image 3 times! +on: + # to allow to wait for a docker image to be published to proceed in another workflow + workflow_call: + +jobs: + build-amd64: + runs-on: ubuntu-24.04 + steps: + - name: Check out the repo + uses: actions/checkout@v4 + + # this is needed to address this issue according to the comment https://github.com/devcontainers/ci/issues/271#issuecomment-2301764487 + # otherwise our TourmalineCore org name cannot be used in docker image names, only tourmalinecore + - name: Add Registry Image Env Var With Lowercase Organization and Repo Name + run: | + echo "REGISTRY_IMAGE=ghcr.io/${GITHUB_REPOSITORY,,}" >>${GITHUB_ENV} + + - name: Prepare + run: | + platform=linux/amd64 + echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV + + - name: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY_IMAGE }} + + - name: Log in to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build and push by digest + id: build + uses: docker/build-push-action@v6 + with: + platforms: linux/amd64 + context: . + file: ./Api/Dockerfile + build-args: | + EXCLUDE_UNIT_TESTS_FROM_BUILD=true + labels: ${{ steps.meta.outputs.labels }} + tags: ${{ env.REGISTRY_IMAGE }} + outputs: type=image,push-by-digest=true,name-canonical=true,push=true + + - name: Export digest + run: | + mkdir -p ${{ runner.temp }}/digests + digest="${{ steps.build.outputs.digest }}" + touch "${{ runner.temp }}/digests/${digest#sha256:}" + + - name: Upload digest + uses: actions/upload-artifact@v4 + with: + name: digests-${{ env.PLATFORM_PAIR }} + path: ${{ runner.temp }}/digests/* + if-no-files-found: error + retention-days: 1 + + build-arm64: + runs-on: ubuntu-24.04-arm + steps: + - name: Check out the repo + uses: actions/checkout@v4 + + # this is needed to address this issue according to the comment https://github.com/devcontainers/ci/issues/271#issuecomment-2301764487 + # otherwise our TourmalineCore org name cannot be used in docker image names, only tourmalinecore + - name: Add Registry Image Env Var With Lowercase Organization and Repo Name + run: | + echo "REGISTRY_IMAGE=ghcr.io/${GITHUB_REPOSITORY,,}" >>${GITHUB_ENV} + + - name: Prepare + run: | + platform=linux/arm64 + echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV + + - name: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY_IMAGE }} + + - name: Log in to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build and push by digest + id: build + uses: docker/build-push-action@v6 + with: + platforms: linux/arm64 + context: . + file: ./Api/Dockerfile + build-args: | + EXCLUDE_UNIT_TESTS_FROM_BUILD=true + labels: ${{ steps.meta.outputs.labels }} + tags: ${{ env.REGISTRY_IMAGE }} + outputs: type=image,push-by-digest=true,name-canonical=true,push=true + + - name: Export digest + run: | + mkdir -p ${{ runner.temp }}/digests + digest="${{ steps.build.outputs.digest }}" + touch "${{ runner.temp }}/digests/${digest#sha256:}" + + - name: Upload digest + uses: actions/upload-artifact@v4 + with: + name: digests-${{ env.PLATFORM_PAIR }} + path: ${{ runner.temp }}/digests/* + if-no-files-found: error + retention-days: 1 + merge: + runs-on: ubuntu-24.04 + needs: + - build-amd64 + - build-arm64 + steps: + # this is needed to address this issue according to the comment https://github.com/devcontainers/ci/issues/271#issuecomment-2301764487 + # otherwise our TourmalineCore org name cannot be used in docker image names, only tourmalinecore + - name: Add Registry Image Env Var With Lowercase Organization and Repo Name + run: | + echo "REGISTRY_IMAGE=ghcr.io/${GITHUB_REPOSITORY,,}" >>${GITHUB_ENV} + + - name: Download digests + uses: actions/download-artifact@v4 + with: + path: ${{ runner.temp }}/digests + pattern: digests-* + merge-multiple: true + + - name: Log in to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Check out the repo + uses: actions/checkout@v4 + + - name: Add SEMVER_VERSION Env Var with Value from __version File + run: | + echo "SEMVER_VERSION=$(cat __version)" >>${GITHUB_ENV} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY_IMAGE }} + tags: | + # minimal (short sha) + type=sha + # full length sha + type=sha,format=long + # SemVer human readable version + type=raw,value=${{ env.SEMVER_VERSION }} + # set latest tag for default branch + # https://github.com/docker/metadata-action/issues/171 explains how to tag latest only on default branch + type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) }} + env: + # https://github.com/docker/metadata-action/issues/283 + # without this flag it won't tag the image using the commit SHA + # for non push events like pull_request ones it requires this :( + DOCKER_METADATA_PR_HEAD_SHA: true + + - name: Create manifest list and push + working-directory: ${{ runner.temp }}/digests + run: | + docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ + $(printf '${{ env.REGISTRY_IMAGE }}@sha256:%s ' *) + + - name: Inspect image + run: | + docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ steps.meta.outputs.version }} diff --git a/.github/workflows/.reusable-e2e-tests-against-prod.yml b/.github/workflows/.reusable-e2e-tests-against-prod.yml new file mode 100644 index 0000000..f2a375b --- /dev/null +++ b/.github/workflows/.reusable-e2e-tests-against-prod.yml @@ -0,0 +1,32 @@ +name: E2E Tests Against Prod + +on: + workflow_call: + +jobs: + e2e-test-against-prod: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'temurin' + + - name: Download Karate JAR + run: | + curl -L https://github.com/karatelabs/karate/releases/download/v1.5.1/karate-1.5.1.jar -o karate.jar + + - name: Run E2E Tests Against Prod Env + run: | + # Learn more about '> /dev/null 2>&1': https://stackoverflow.com/a/42919998 + # In essence it merges output and error streams and doesn't show errors in the terminal to avoid leakage of secrets in the pipeline + java -jar karate.jar . > /dev/null 2>&1 + env: + "AUTH_FIRST_TENANT_LOGIN_WITH_ALL_PERMISSIONS": ${{ secrets.INNER_CIRCLE_PROD_AUTH_FIRST_TENANT_LOGIN_WITH_ALL_PERMISSIONS }} + "AUTH_FIRST_TENANT_PASSWORD_WITH_ALL_PERMISSIONS": ${{ secrets.INNER_CIRCLE_PROD_AUTH_FIRST_TENANT_PASSWORD_WITH_ALL_PERMISSIONS }} + "AUTH_API_ROOT_URL": ${{ secrets.INNER_CIRCLE_PROD_AUTH_API_ROOT_URL }} + "API_ROOT_URL": ${{ secrets.INNER_CIRCLE_PROD_DOCUMENTS_API_ROOT_URL }} + "SHOULD_USE_FAKE_EXTERNAL_DEPENDENCIES": "false" diff --git a/.github/workflows/deploy-to-prod-from-default.yml b/.github/workflows/deploy-to-prod-from-default.yml new file mode 100644 index 0000000..96b60d5 --- /dev/null +++ b/.github/workflows/deploy-to-prod-from-default.yml @@ -0,0 +1,43 @@ +name: Deploy to Prod + +on: + push: + branches: + - master + +jobs: + docker-build-and-push: + uses: ./.github/workflows/.reusable-docker-build-and-push.yml + + deploy-to-prod: + needs: [docker-build-and-push] + runs-on: ubuntu-24.04 + steps: + - name: Check out the repo + uses: actions/checkout@v4 + + - name: Create default global .kube/config file + run: | + cd $HOME + mkdir .kube + echo "${{ secrets.INNER_CIRCLE_PROD_KUBECONFIG }}" > .kube/config + + - name: Deploy + uses: helmfile/helmfile-action@v1.9.0 + with: + helmfile-version: 'v0.164.0' + helm-version: 'v3.18.0' + helmfile-args: > + apply --suppress-diff --namespace ${{ secrets.INNER_CIRCLE_PROD_NAMESPACE }} -f ci/helmfile.yaml + --state-values-set image.tag=sha-${{ github.sha }} + --state-values-set ingress.hostname=${{ secrets.INNER_CIRCLE_PROD_HOSTNAME }} + --state-values-set extraSecretEnvVars.ConnectionStrings__DefaultConnection=${{ secrets.INNER_CIRCLE_PROD_DOCUMENTS_DB_CONNECTION_STRING }} + --state-values-set extraSecretEnvVars.AuthenticationOptions__PublicSigningKey=${{ secrets.INNER_CIRCLE_PROD_PUBLIC_SIGNING_KEY }} + --state-values-set extraSecretEnvVars.ExternalDepsUrls__EmployeesApiRootUrl=${{ secrets.INNER_CIRCLE_PROD_EMPLOYEES_API_ROOT_URL }} + --state-values-set extraSecretEnvVars.InnerCircleServiceUrls__EmailSenderServiceUrl=${{ secrets.INNER_CIRCLE_PROD_EMAIL_SENDER_SERVICE_URL }} + helmfile-auto-init: "false" + + run-e2e-tests: + uses: ./.github/workflows/.reusable-e2e-tests-against-prod.yml + needs: [deploy-to-prod] + secrets: inherit diff --git a/.github/workflows/docker-build-and-push.yml b/.github/workflows/docker-build-and-push.yml deleted file mode 100644 index e39b85d..0000000 --- a/.github/workflows/docker-build-and-push.yml +++ /dev/null @@ -1,57 +0,0 @@ -name: Publish Docker image - -on: - push: - branches: - - master - - feature/* - # to allow to wait for a docker image to be published to proceed in another workflow - workflow_call: - -jobs: - push_to_registry: - name: Push Docker image to Git Registry - runs-on: ubuntu-22.04 - permissions: - packages: write - contents: read - attestations: write - steps: - - name: Check out the repo - uses: actions/checkout@v4 - # multi-platform build configured using this https://docs.docker.com/build/ci/github-actions/multi-platform/ - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - name: Log in to GitHub Container Registry - uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Extract metadata (tags, labels) for Docker - id: meta - uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 - with: - images: ghcr.io/tourmalinecore/${{ github.event.repository.name }} - tags: | - # minimal (short sha) - type=sha - # full length sha - type=sha,format=long - # set latest tag for default branch - # https://github.com/docker/metadata-action/issues/171 explains how to tag latest only on default branch - type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) }} - - - name: Build and push Docker image - id: push - uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671 - with: - context: . - file: ./Api/Dockerfile - push: true - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - platforms: linux/amd64,linux/arm64 \ No newline at end of file diff --git a/.github/workflows/e2e-tests-on-pull-request.yml b/.github/workflows/e2e-tests-on-pull-request.yml new file mode 100644 index 0000000..af93da0 --- /dev/null +++ b/.github/workflows/e2e-tests-on-pull-request.yml @@ -0,0 +1,76 @@ +name: E2E Tests in PR + +on: + pull_request: + types: [opened, synchronize, reopened] + +jobs: + # this is needed to wait for the new docker image to be build and published to the registry + # so that we can use the image to run the service of the needed commit related version as part of local-env + # the idea is taken from here https://stackoverflow.com/a/71489231 + docker-build-and-push: + uses: ./.github/workflows/.reusable-docker-build-and-push.yml + + e2e-test-against-local-env: + runs-on: ubuntu-24.04 + needs: [docker-build-and-push] + steps: + - name: Checkout local-env + uses: actions/checkout@v4 + with: + repository: TourmalineCore/inner-circle-local-env + + - name: Deploy Local Env to Kind k8s + uses: devcontainers/ci@v0.3 + with: + cacheFrom: ghcr.io/tourmalinecore/inner-circle-local-env-devcontainer + runCmd: | + # we need to override "latest" image tag of ui inside local-env to run e2e against the current commit ui version and not against latest from master + # We tried to use yq to change the image tag, but in the values files for helmfile we have non-yaml code that yq can`t parse or ignore + # so for that reason we use Stream EDitor which can find needed string using regular expressions and change it to a new value + # The -i flag is needed to write new image tag directly to values file + sed -i "0,/tag:.*/s//tag: \"sha-${{ github.event.pull_request.head.sha }}\"/" deploy/values-documents-api.yaml.gotmpl + + # we need to override "latest" ref of service chart inside local-env to run tests against the current commit service chart version and not against latest from master + sed -i "0,/git+https:\/\/github.com\/TourmalineCore\/${{ github.event.repository.name }}.git?ref=.*/s//git+https:\/\/github.com\/TourmalineCore\/${{ github.event.repository.name }}.git?ref=${{ github.event.pull_request.head.sha }}/" deploy/helmfile.yaml + + sed -i "0,/git::https:\/\/github.com\/TourmalineCore\/${{ github.event.repository.name }}.git@\/ci\/values.yaml?ref=.*/s//git::https:\/\/github.com\/TourmalineCore\/${{ github.event.repository.name }}.git@\/ci\/values.yaml?ref=${{ github.event.pull_request.head.sha }}/" deploy/helmfile.yaml + + kind create cluster --name inner-circle --config kind-local-config.yaml --kubeconfig ./.inner-circle-cluster-kubeconfig + # we need to properly expose KUBECONFIG as an absolute path, pwd prints current working directory path + export KUBECONFIG=$(pwd)/.inner-circle-cluster-kubeconfig + + helmfile --environment local --namespace local -f deploy/helmfile.yaml apply + push: never + + - name: Check out the repo + uses: actions/checkout@v4 + + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'temurin' + + - name: Download Karate JAR + run: | + curl -L https://github.com/karatelabs/karate/releases/download/v1.5.1/karate-1.5.1.jar -o karate.jar + + - name: Run E2E Tests Against Local Env + run: | + java -jar karate.jar . + env: + "AUTH_FIRST_TENANT_LOGIN_WITH_ALL_PERMISSIONS": "malfoy@tourmalinecore.com" + "AUTH_FIRST_TENANT_PASSWORD_WITH_ALL_PERMISSIONS": "Serpens1!" + "AUTH_API_ROOT_URL": "http://localhost:30090/api/auth" + "API_ROOT_URL": "http://localhost:30090/api/documents" + "SHOULD_USE_FAKE_EXTERNAL_DEPENDENCIES": "false" + + e2e-karate-tests-in-docker-compose: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - name: Run service via docker-compose and run Karate-tests + run: | + # The option --exit-code-from ensures that the command's exit code exactly matches the exit code of the specified service. + docker compose --profile MockForPullRequest up --exit-code-from inner-circle-documents-api-karate-tests diff --git a/.github/workflows/karate-tests-on-pull-request.yml b/.github/workflows/karate-tests-on-pull-request.yml deleted file mode 100644 index 6b67932..0000000 --- a/.github/workflows/karate-tests-on-pull-request.yml +++ /dev/null @@ -1,99 +0,0 @@ -name: E2E Tests - -on: - push: - branches: - - feature/* - -jobs: - # this is needed to wait for the new docker image to be build and published to the registry - # so that we can use the image to run ui of the needed commit related version as part of local-env - # the idea is taken from here https://stackoverflow.com/a/71489231 - push_to_registry: - uses: ./.github/workflows/docker-build-and-push.yml - # without this it cannot login to the registry - secrets: inherit - - e2e-test-without-local-env: - runs-on: ubuntu-24.04 - steps: - - uses: actions/checkout@v4 - - name: Run service via docker-compose and run Karate-tests - # Hide credentials and token from logs, get the number of failed and passed tests - # Find text with 'failed' and 'passed' in logs from karate-testing container - run: | - LOGS=$(docker compose --profile MockForPullRequest up --abort-on-container-exit) - FILTERED_LOGS=$(echo "$LOGS" | sed -E 's/"login":"[^"]*"/"login":"****"/g' \ - | sed -E 's/"password":"[^"]*"/"password":"****"/g' \ - | sed -E 's/"accessToken":[^,}]*"[^"]*"/"accessToken":"****"/g' \ - | sed -E 's/"Authorization":"[^"]*"/"Authorization":"****"/g' \ - | sed -E 's/"X-DEBUG-TOKEN":[^,}]*"[^"]*"/"X-DEBUG-TOKEN":"****"/g' \ - | sed -E 's/accessToken":\{[^}]*\}/accessToken":{"value":"****"}/g' \ - | sed -E 's/X-DEBUG-TOKEN: [^ ]*/X-DEBUG-TOKEN: ****/g') - echo "$FILTERED_LOGS" - FAILED=$(echo "$FILTERED_LOGS" | grep -oP 'failed: *\K\d+') - PASSED=$(echo "$FILTERED_LOGS" | grep -oP 'passed: *\K\d+') - echo "Failed tests: $FAILED" - echo "Passed tests: $PASSED" - if [ "$FAILED" -gt 0 ]; then - echo "Failed tests found! Failing the pipeline..." - exit 1 - fi - if [ "$PASSED" -eq 0 ]; then - echo "No tests passed! Failing the pipeline..." - exit 1 - fi - - e2e-test-with-local-env: - name: Run karate tests in local env - runs-on: ubuntu-22.04 - needs: [push_to_registry] - steps: - - name: Checkout local-env - uses: actions/checkout@v4 - with: - repository: TourmalineCore/inner-circle-local-env - - - name: Deploy Local Env to Kind k8s - uses: devcontainers/ci@v0.3 - with: - runCmd: | - # we need to override "latest" image tag of ui inside local-env to run e2e against the current commit ui version and not against latest from master - # We tried to use yq to change the image tag, but in the values files for helmfile we have non-yaml code that yq can`t parse or ignore - # so for that reason we use Stream EDitor which can find needed string using regular expressions and change it to a new value - # The -i flag is needed to write new image tag directly to values file - sed -i "0,/tag:.*/s//tag: \"sha-${{ github.sha }}\"/" deploy/values-documents-api.yaml.gotmpl - - # we need to override "latest" ref of service chart inside local-env to run tests against the current commit service chart version and not against latest from master - sed -i "0,/git+https:\/\/github.com\/TourmalineCore\/${{ github.event.repository.name }}.git?ref=.*/s//git+https:\/\/github.com\/TourmalineCore\/${{ github.event.repository.name }}.git?ref=${{ github.sha }}/" deploy/helmfile.yaml - - sed -i "0,/git::https:\/\/github.com\/TourmalineCore\/${{ github.event.repository.name }}.git@\/Api\/ci\/values.yaml?ref=.*/s//git::https:\/\/github.com\/TourmalineCore\/${{ github.event.repository.name }}.git@\/Api\/ci\/values.yaml?ref=${{ github.sha }}/" deploy/helmfile.yaml - - kind create cluster --name inner-circle --config kind-local-config.yaml --kubeconfig ./.inner-circle-cluster-kubeconfig - # we need to properly expose KUBECONFIG as an absolute path, pwd prints current working directory path - export KUBECONFIG=$(pwd)/.inner-circle-cluster-kubeconfig - - helmfile --environment local --namespace local -f deploy/helmfile.yaml apply - push: never - - - name: Checkout api - uses: actions/checkout@v4 - - - name: Set up JDK 17 - uses: actions/setup-java@v3 - with: - java-version: '17' - distribution: 'temurin' - - - name: Download Karate JAR - run: | - curl -L https://github.com/karatelabs/karate/releases/download/v1.5.1/karate-1.5.1.jar -o karate.jar - - - name: Run Karate Tests - run: | - java -jar karate.jar . - env: - AUTH_API_ROOT_URL: "http://localhost:30090/api" - API_ROOT_URL: "http://localhost:30090" - AUTH_LOGIN: "ceo@tourmalinecore.com" - AUTH_PASSWORD: "cEoPa$$wo1d" \ No newline at end of file diff --git a/.github/workflows/lint-on-pull-request.yml b/.github/workflows/lint-on-pull-request.yml new file mode 100644 index 0000000..a405562 --- /dev/null +++ b/.github/workflows/lint-on-pull-request.yml @@ -0,0 +1,21 @@ +name: Lint + +on: + pull_request: + types: [opened, synchronize, reopened] + +jobs: + unit-tests: + name: Run linting + runs-on: ubuntu-24.04 + steps: + - name: Check out the repo + uses: actions/checkout@v4 + + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 8.0.x + + - name: Check there are no non-formatted files + run: dotnet format --verify-no-changes diff --git a/.github/workflows/prod-docker-publish.yml b/.github/workflows/prod-docker-publish.yml deleted file mode 100644 index 42be3de..0000000 --- a/.github/workflows/prod-docker-publish.yml +++ /dev/null @@ -1,45 +0,0 @@ -name: Deploy to Prod - -on: - push: - branches: - - master - -jobs: - # this is needed to wait for the new docker image to be build and published to the registry - # so that we can use the image to run ui of the needed commit related version as part of local-env - # the idea is taken from here https://stackoverflow.com/a/71489231 - push_to_registry: - uses: ./.github/workflows/docker-build-and-push.yml - # without this it cannot login to the registry - secrets: inherit - - deploy-to-prod: - name: Deploy service to k8s for prod environment - needs: [push_to_registry] - runs-on: ubuntu-22.04 - steps: - - name: Check out the repo - uses: actions/checkout@v4 - - - name: Create default global .kube/config file - run: | - cd $HOME - mkdir .kube - echo "${{ secrets.KUBECONFIG }}" > .kube/config - - - name: Deploy - uses: helmfile/helmfile-action@v1.9.0 - with: - helmfile-version: 'v0.164.0' - helm-version: 'v3.18.0' - helmfile-args: > - apply --suppress-diff --namespace dev-inner-circle -f Api/ci/helmfile.yaml - --state-values-set image.tag=sha-${{ github.sha }} - --state-values-set ingress.enabled=true - --state-values-set ingress.hostname=${{ secrets.HOST }} - --state-values-set extraSecretEnvVars.ConnectionStrings__DefaultConnection=${{ secrets.POSTGRESQL_CONNECTION_STRING }} - --state-values-set extraSecretEnvVars.AuthenticationOptions__PublicSigningKey=${{ secrets.PUBLIC_SIGNING_KEY }} - --state-values-set extraSecretEnvVars.InnerCircleServiceUrls__EmployeesServiceUrl=${{ secrets.EMPLOYEES_SERVICE_URL }} - --state-values-set extraSecretEnvVars.InnerCircleServiceUrls__EmailSenderServiceUrl=${{ secrets.EMAIL_SENDER_SERVICE_URL }} - helmfile-auto-init: "false" \ No newline at end of file diff --git a/.github/workflows/unit-tests-on-pull-request.yml b/.github/workflows/unit-tests-on-pull-request.yml index 5018e60..7258e74 100644 --- a/.github/workflows/unit-tests-on-pull-request.yml +++ b/.github/workflows/unit-tests-on-pull-request.yml @@ -1,23 +1,27 @@ name: Unit Tests on: - push: - branches: - - feature/* + pull_request: + types: [opened, synchronize, reopened] jobs: unit-tests: name: Run unit tests - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - - name: Checkout + - name: Check out the repo uses: actions/checkout@v4 + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 8.0.x + - name: Restore application dependencies - run: dotnet restore + run: dotnet restore - name: Build application - run: dotnet build + run: dotnet build --property:TreatWarningsAsErrors=true - - name: Run unit tests - run: dotnet test \ No newline at end of file + - name: Run unit-tests + run: dotnet test diff --git a/Application/InnerCircleHttpClient.cs b/Application/InnerCircleHttpClient.cs index ec85e36..1642668 100644 --- a/Application/InnerCircleHttpClient.cs +++ b/Application/InnerCircleHttpClient.cs @@ -44,7 +44,7 @@ public async Task> GetEmployeesAsync() var response = await _client.GetStringAsync(link); - return JsonConvert.DeserializeObject>(response); + return JsonConvert.DeserializeObject>(response)!; } public async Task SendMailingPayslips(List payslips, List employees) diff --git a/Application/Services/EmployeeDto.cs b/Application/Services/EmployeeDto.cs index b0cd7b2..3a89d54 100644 --- a/Application/Services/EmployeeDto.cs +++ b/Application/Services/EmployeeDto.cs @@ -2,10 +2,10 @@ namespace Application.Services; public class EmployeesDto { - public List Employees { get; set; } + public required List Employees { get; set; } } public class EmployeeDto { - public string LastName { get; set; } + public required string LastName { get; set; } } diff --git a/Application/Services/Options/InnerCircleServiceUrl.cs b/Application/Services/Options/InnerCircleServiceUrl.cs index d3bbede..58e94a0 100644 --- a/Application/Services/Options/InnerCircleServiceUrl.cs +++ b/Application/Services/Options/InnerCircleServiceUrl.cs @@ -2,7 +2,7 @@ namespace Application.Services.Options; public class InnerCircleServiceUrls { - public string EmployeesServiceUrl { get; set; } + public required string EmployeesServiceUrl { get; set; } - public string EmailSenderServiceUrl { get; set; } + public required string EmailSenderServiceUrl { get; set; } } diff --git a/Core/Document.cs b/Core/Document.cs index 3a64b4e..2eb4015 100644 --- a/Core/Document.cs +++ b/Core/Document.cs @@ -4,7 +4,7 @@ public class Document { public long Id { get; set; } - public string Name { get; set; } + public required string Name { get; set; } public Document(string name) { diff --git a/Core/PayslipsItem.cs b/Core/PayslipsItem.cs index 87a8d60..a97e6b0 100644 --- a/Core/PayslipsItem.cs +++ b/Core/PayslipsItem.cs @@ -4,9 +4,9 @@ namespace Core; public class PayslipsItem { - public IFormFile File { get; set; } + public required IFormFile File { get; set; } - public string LastName { get; set; } + public required string LastName { get; set; } public PayslipsItem(string lastName, IFormFile file) { diff --git a/DataAccess/DocumentsDbContext.cs b/DataAccess/DocumentsDbContext.cs index fcbcd9a..3cb1cb8 100644 --- a/DataAccess/DocumentsDbContext.cs +++ b/DataAccess/DocumentsDbContext.cs @@ -5,7 +5,7 @@ namespace DataAccess; public class DocumentsDbContext : DbContext { - public DbSet Documents { get; set; } + public required DbSet Documents { get; set; } public DocumentsDbContext(DbContextOptions options) : base(options) { diff --git a/docker-compose.yml b/docker-compose.yml index 8a29cba..30274dc 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -82,8 +82,8 @@ services: - .:/karate environment: # here the port is 1080 because it needs to be an internal port, not an external which is 8504 in this case - AUTH_API_ROOT_URL: "http://inner-circle-documents-api-mock-server:1080/api" - API_ROOT_URL: "http://inner-circle-documents-api" + AUTH_API_ROOT_URL: "http://inner-circle-documents-api-mock-server:1080/api/auth" + API_ROOT_URL: "http://inner-circle-documents-api/api" SHOULD_USE_FAKE_EXTERNAL_DEPENDENCIES: "true" networks: - inner-circle-documents-api-network diff --git a/e2e/documents-get-employees.feature b/e2e/documents-get-employees.feature index a3d183a..5c0e07e 100644 --- a/e2e/documents-get-employees.feature +++ b/e2e/documents-get-employees.feature @@ -15,7 +15,7 @@ Scenario: Get Employees # Authentication Given url authApiRootUrl - And path '/auth/login' + And path '/login' And request """ { @@ -32,7 +32,7 @@ Scenario: Get Employees # Get Employees Given url apiRootUrl - And path '/api/documents/getEmployees' + And path '/getEmployees' When method GET Then status 200 And match response.employees contains