diff --git a/.dockerignore b/.dockerignore index 91fc64c..01efac9 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,4 +1,5 @@ **/.classpath +**/.dockerignore **/.env **/.git **/.gitignore @@ -21,4 +22,43 @@ **/secrets.dev.yaml **/values.dev.yaml LICENSE +README.md +!**/.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..2d32c99 --- /dev/null +++ b/.github/workflows/.reusable-docker-build-and-push.yml @@ -0,0 +1,180 @@ +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: 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 + # 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 }} \ No newline at end of file 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..0af23b3 --- /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 Local 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_ACCOUNTS_API_ROOT_URL }} + "SHOULD_USE_FAKE_EXTERNAL_DEPENDENCIES": "false" \ No newline at end of file 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..c1d0315 --- /dev/null +++ b/.github/workflows/deploy-to-prod-from-default.yml @@ -0,0 +1,45 @@ +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 Api/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_ACCOUNTS_DB_CONNECTION_STRING }} + --state-values-set extraSecretEnvVars.AuthenticationOptions__PublicSigningKey=${{ secrets.INNER_CIRCLE_PROD_PUBLIC_SIGNING_KEY }} + --state-values-set extraSecretEnvVars.HttpUrls__AuthServiceUrl=${{ secrets.INNER_CIRCLE_PROD_AUTH_SERVICE_URL }} + --state-values-set extraSecretEnvVars.HttpUrls__EmployeesServiceUrl=${{ secrets.INNER_CIRCLE_PROD_EMPLOYEES_SERVICE_URL }} + --state-values-set extraSecretEnvVars.AccountValidationOptions__CorporateEmailDomain=${{ secrets.INNER_CIRCLE_PROD_CORPORATE_EMAIL_DOMAIN }} + --state-values-set extraSecretEnvVars.AccountValidationOptions__IgnoreCorporateDomainValidationRule=${{ secrets.INNER_CIRCLE_PROD_IGNORE_CORPORATE_DOMAIN_VALIDATION_RULE }} + helmfile-auto-init: "false" + + run-e2e-tests: + uses: ./.github/workflows/.reusable-e2e-tests-against-prod.yml + needs: [deploy-to-prod] + secrets: inherit \ No newline at end of file diff --git a/.github/workflows/deploy-to-prod.yml b/.github/workflows/deploy-to-prod.yml deleted file mode 100644 index 37b237e..0000000 --- a/.github/workflows/deploy-to-prod.yml +++ /dev/null @@ -1,87 +0,0 @@ -name: Deploy to Prod and e2e test 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.DEV_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.hostname=${{ secrets.DEV_HOST }} - --state-values-set extraSecretEnvVars.ConnectionStrings__DefaultConnection=${{ secrets.DEV_POSTGRESQL_CONNECTION_STRING }} - --state-values-set extraSecretEnvVars.AuthenticationOptions__PublicSigningKey=${{ secrets.DEV_AUTH_PUBLIC_SIGNING_KEY }} - --state-values-set extraSecretEnvVars.HttpUrls__AuthServiceUrl=${{ secrets.DEV_AUTH_SERVICE_URL }} - --state-values-set extraSecretEnvVars.HttpUrls__EmployeesServiceUrl=${{ secrets.DEV_EMPLOYEE_SERVICE_URL }} - --state-values-set extraSecretEnvVars.AccountValidationOptions__CorporateEmailDomain=${{ secrets.DEV_CORPORATE_EMAIL_DOMAIN }} - --state-values-set extraSecretEnvVars.AccountValidationOptions__IgnoreCorporateDomainValidationRule=${{ secrets.DEV_IGNORE_CORPORATE_DOMAIN_VALIDATION_RULE }} - helmfile-auto-init: "false" - - e2e-test-prod: - runs-on: ubuntu-22.04 - needs: [deploy-to-prod] - steps: - - name: Check out the repo - uses: actions/checkout@v4 - - # Get secrets to sign in - - name: Set up Docker Compose environment variables - run: | - echo AUTH_LOGIN=${{ secrets.DEV_E2E_AUTO_TEST_LOGIN }} >> .env - echo AUTH_PASSWORD=${{ secrets.DEV_E2E_AUTO_TEST_PASSWORD }} >> .env - - - name: Run service via docker-compose and run Karate-tests - run: | - # Get logs - LOGS=$(docker compose --profile production-e2e-tests up --abort-on-container-exit) - # Filter logs and mask sensitive information - 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' \ - | sed -E 's/Authorization: [^ ]*/Authorization: ****/g') - echo "$FILTERED_LOGS" - # Count failed and passed tests - 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 diff --git a/.github/workflows/docker-build-and-push.yml b/.github/workflows/docker-build-and-push.yml deleted file mode 100644 index 6df0d38..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: ./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..827cfac --- /dev/null +++ b/.github/workflows/e2e-tests-on-pull-request.yml @@ -0,0 +1,67 @@ +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-accounts-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@\/Api\/ci\/values.yaml?ref=.*/s//git::https:\/\/github.com\/TourmalineCore\/${{ github.event.repository.name }}.git@\/Api\/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/account-management" + "SHOULD_USE_FAKE_EXTERNAL_DEPENDENCIES": "false" \ No newline at end of file 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 1f5e65e..0000000 --- a/.github/workflows/karate-tests-on-pull-request.yml +++ /dev/null @@ -1,67 +0,0 @@ -name: Run karate tests in PR - -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-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 - yq -i '.image.tag = "sha-${{ github.sha }}"' deploy/values-accounts-api.yaml.gotmpl - - 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 - # this variable is used by local-env helmfile to use current feature branch helm chart values.yaml file - # this is needed for a case when as part of the feature the chart was changed and is different from master branch - # this should properly fill the feature branch name in spite of the pipeline trigger source (PR, commit, etc.) - # https://stackoverflow.com/a/71158878 - env: | - ACCOUNTS_API_BRANCH=${{ github.head_ref || github.ref_name }} - - - 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/auth" - API_ROOT_URL: "http://localhost:30090/api" - AUTH_LOGIN: "ceo@tourmalinecore.com" - AUTH_PASSWORD: "cEoPa$$wo1d" - SHOULD_USE_FAKE_EXTERNAL_DEPENDENCIES: "false" \ No newline at end of file diff --git a/Api/Dockerfile b/Api/Dockerfile new file mode 100644 index 0000000..b3d56fe --- /dev/null +++ b/Api/Dockerfile @@ -0,0 +1,30 @@ +# See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging. + +# This stage is used when running from VS in fast mode (Default for Debug configuration) +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +# use root to be able to use privilidged port 80 +# https://github.com/dotnet/aspnetcore/discussions/53015 +USER root +WORKDIR /app +EXPOSE 80 + +# This stage is used to build the service project +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +ARG BUILD_CONFIGURATION=Release +ARG EXCLUDE_UNIT_TESTS_FROM_BUILD=${EXCLUDE_UNIT_TESTS_FROM_BUILD} +WORKDIR /src +COPY . . +WORKDIR "/src/Api" +RUN dotnet build "./Api.csproj" -c $BUILD_CONFIGURATION -o /app/build /p:EXCLUDE_UNIT_TESTS_FROM_BUILD=$EXCLUDE_UNIT_TESTS_FROM_BUILD + +# This stage is used to publish the service project to be copied to the final stage +FROM build AS publish +ARG BUILD_CONFIGURATION=Release +RUN dotnet publish "./Api.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false /p:EXCLUDE_UNIT_TESTS_FROM_BUILD=$EXCLUDE_UNIT_TESTS_FROM_BUILD + +# This stage is used in production or when running from VS in regular mode (Default when not using the Debug configuration) +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENV ASPNETCORE_HTTP_PORTS=80 +ENTRYPOINT ["dotnet", "Api.dll"] \ No newline at end of file diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 8bfa5af..0000000 --- a/Dockerfile +++ /dev/null @@ -1,19 +0,0 @@ -FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base -WORKDIR /app -EXPOSE 80 - -FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build -WORKDIR /src -COPY ["Api/Api.csproj", "Api/"] -RUN dotnet restore "Api/Api.csproj" -COPY . . -WORKDIR "/src/Api" -RUN dotnet build "Api.csproj" -c Release -o /app/build - -FROM build AS publish -RUN dotnet publish "Api.csproj" -c Release -o /app/publish /p:UseAppHost=false - -FROM base AS final -WORKDIR /app -COPY --from=publish /app/publish . -ENTRYPOINT ["dotnet", "Api.dll"] diff --git a/E2E-basic-flow.feature b/E2E-basic-flow.feature index 005dd48..e5db5cc 100644 --- a/E2E-basic-flow.feature +++ b/E2E-basic-flow.feature @@ -11,8 +11,8 @@ Scenario: CRUD operations test flow * def jsUtils = read('jsUtils.js') * def authApiRootUrl = jsUtils().getEnvVariable('AUTH_API_ROOT_URL') * def apiRootUrl = jsUtils().getEnvVariable('API_ROOT_URL') - * def authLogin = jsUtils().getEnvVariable('AUTH_LOGIN') - * def authPassword = jsUtils().getEnvVariable('AUTH_PASSWORD') + * def authLogin = jsUtils().getEnvVariable('AUTH_FIRST_TENANT_LOGIN_WITH_ALL_PERMISSIONS') + * def authPassword = jsUtils().getEnvVariable('AUTH_FIRST_TENANT_PASSWORD_WITH_ALL_PERMISSIONS') # Authentication Given url authApiRootUrl @@ -29,7 +29,7 @@ Scenario: CRUD operations test flow # create tenant Given url apiRootUrl - Given path '/account-management/tenants' + Given path '/tenants' * def tenantName = 'Test tenant' + Math.random() And request { name: '#(tenantName)' } When method POST @@ -37,7 +37,7 @@ Scenario: CRUD operations test flow * def tenantId = response # create role - Given path '/account-management/roles/create' + Given path '/roles/create' * def roleName = 'Test role' + Math.random() And request { name: '#(roleName)', permissions: ["ViewAccounts"] } When method POST @@ -45,7 +45,7 @@ Scenario: CRUD operations test flow * def roleId = response # create account - Given path '/account-management/accounts/create' + Given path '/accounts/create' * def firstName = 'test-' + Math.random() * def lastName = 'test-' + Math.random() * def middleName = 'test-' + Math.random() @@ -57,7 +57,7 @@ Scenario: CRUD operations test flow * def accountId = response # verify the account has created roleId and tenantId - Given path '/account-management/accounts/findById/' + accountId + Given path '/accounts/findById/' + accountId And header Authorization = accessTokenForExternalDeps When method GET Then status 200 @@ -75,18 +75,18 @@ Scenario: CRUD operations test flow * match responseTenantId == tenantId # delete account - Given path '/account-management/accounts/delete-account' + Given path '/accounts/delete-account' And header Authorization = accessTokenForExternalDeps And request { corporateEmail: '#(corporateEmail)'} When method POST Then status 200 # delete role - Given path '/account-management/roles/' + roleId + Given path '/roles/' + roleId When method DELETE Then status 200 # delete tenant - Given path '/account-management/tenants/' + tenantId + Given path '/tenants/' + tenantId When method DELETE Then status 200