diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7b610381..23548f70 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -80,18 +80,16 @@ default: - name: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/docker:${DOCKER_VERSION}-dind alias: docker variables: - DOCKER_BUILDARGS: "--push" + DOCKER_BUILDARGS: "--push --cache-to=$CI_REGISTRY_IMAGE:cache --cache-from=$CI_REGISTRY_IMAGE:cache" before_script: - apk add make bash git - *dind-login # NOTE: If we're running on a PR, do not build multiplatform - - test "$CI_COMMIT_REF_PROTECTED" != "true" && unset DOCKER_PLATFORM - - if test -n "${DOCKER_PLATFORM}"; then - docker context create ci; - docker builder create --name ci-builder ci; - export DOCKER_BUILDARGS="${DOCKER_BUILDARGS} --builder=ci-builder"; - unset DOCKER_HOST; - fi + - test "$CI_COMMIT_REF_PROTECTED" != "true" && export DOCKER_PLATFORM=linux/amd64 + - docker context create ci; + - docker builder create --name ci-builder ci; + - export DOCKER_BUILDARGS="${DOCKER_BUILDARGS} --builder=ci-builder"; + - unset DOCKER_HOST; build:backend:docker: extends: .template:build:docker @@ -114,14 +112,25 @@ build:backend:docker: build:backend:docker-acceptance: extends: build:backend:docker - before_script: - - apk add make bash git - - *dind-login - # We're only building acceptance test images for CI runner platform. - - unset DOCKER_PLATFORM script: + # We're only building acceptance test images for CI runner platform. + - export DOCKER_PLATFORM=linux/amd64 # NOTE: Only build for test platform (default) for the acceptance test images - make -C backend docker-acceptance + - docker build $DOCKER_BUILDARGS -f backend/tests/Dockerfile.acceptance -t $CI_REGISTRY_IMAGE/acceptance:$CI_COMMIT_REF_NAME backend/tests + +build:backend:docker-integration: + extends: .template:build:docker + rules: + - changes: + paths: ["backend/**/*"] + compare_to: "${RULES_CHANGES_COMPARE_TO_REF}" + when: always + - if: '$CI_COMMIT_REF_PROTECTED == "true"' + when: always + script: + - unset DOCKER_PLATFORM + - docker build $DOCKER_BUILDARGS -f backend/tests/Dockerfile.integration -t $CI_REGISTRY_IMAGE/integration:$CI_COMMIT_REF_NAME backend/tests test:backend:static: stage: test @@ -242,6 +251,7 @@ test:backend:integration: when: on_success tags: - hetzner-amd-beefy + parallel: 2 services: - name: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/docker:${DOCKER_VERSION}-dind alias: docker @@ -250,6 +260,8 @@ test:backend:integration: artifacts: false - job: build:backend:docker-acceptance artifacts: false + - job: build:backend:docker-integration + artifacts: false before_script: - apk add make bash git curl - *dind-login @@ -375,7 +387,6 @@ coveralls:done: tags: - hetzner-amd-beefy - lint:commit: stage: lint needs: [] @@ -394,10 +405,11 @@ changelog: image: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/node:20 stage: changelog variables: - GIT_DEPTH: 0 # Always get the full history - GIT_STRATEGY: clone # Always get the full history - GIT_CLIFF__BUMP__INITIAL_TAG: "4.0.0" # TODO: after the new tag is created, - # remove this variable + GIT_DEPTH: 0 # Always get the full history + GIT_STRATEGY: clone # Always get the full history + GIT_CLIFF__BUMP__INITIAL_TAG: + "4.0.0" # TODO: after the new tag is created, + # remove this variable tags: - hetzner-amd-beefy rules: @@ -422,12 +434,12 @@ changelog: # getting the centralized git cliff config script: - release-please release-pr - --token=${GITHUB_BOT_TOKEN_REPO_FULL} - --repo-url=${GITHUB_REPO_URL} - --target-branch=${CI_COMMIT_REF_NAME} || echo "INFO - release already exists" # workaround because we shifted to prerelease versioning strategy and there's already a PR open + --token=${GITHUB_BOT_TOKEN_REPO_FULL} + --repo-url=${GITHUB_REPO_URL} + --target-branch=${CI_COMMIT_REF_NAME} || echo "INFO - release already exists" # workaround because we shifted to prerelease versioning strategy and there's already a PR open # git cliff: override the changelog - test $GIT_CLIFF == "false" && echo "INFO - Skipping git-cliff" && exit 0 - - git remote add github-${CI_JOB_ID} https://${GITHUB_USER_NAME}:${GITHUB_BOT_TOKEN_REPO_FULL}@github.com/${GITHUB_REPO_URL} || true # Ignore already existing remote + - git remote add github-${CI_JOB_ID} https://${GITHUB_USER_NAME}:${GITHUB_BOT_TOKEN_REPO_FULL}@github.com/${GITHUB_REPO_URL} || true # Ignore already existing remote - gh repo set-default https://${GITHUB_USER_NAME}:${GITHUB_BOT_TOKEN_REPO_FULL}@github.com/${GITHUB_REPO_URL} - RELEASE_PLEASE_PR=$(gh pr list --author "${GITHUB_USER_NAME}" --head "release-please--branches--${CI_COMMIT_REF_NAME}" --json number | jq -r '.[0].number // empty') - test -z "$RELEASE_PLEASE_PR" && echo "No release-please PR found" && exit 0 @@ -459,6 +471,6 @@ release:github: script: - npm install -g release-please - release-please github-release - --token=${GITHUB_BOT_TOKEN_REPO_FULL} - --repo-url=${GITHUB_REPO_URL} - --target-branch=${CI_COMMIT_REF_NAME} + --token=${GITHUB_BOT_TOKEN_REPO_FULL} + --repo-url=${GITHUB_REPO_URL} + --target-branch=${CI_COMMIT_REF_NAME} diff --git a/backend/services/Makefile.common b/backend/services/Makefile.common index 5abca67e..de3f1b06 100644 --- a/backend/services/Makefile.common +++ b/backend/services/Makefile.common @@ -37,8 +37,14 @@ BUILDFLAGS += -tags=$(subst $(_space),$(_comma),$(strip $(BUILDTAGS) $(BUILDTAGS # DOCKER_PLATFORM default is defined with respect to the docker server. # This fixes the default case on darwin where docker is running inside a VM (linux). +# NOTE: The platform always falls back on linux/amd64. define default_docker_platform_template -{{- .OSType}}/{{- if eq .Architecture "aarch64" -}} +{{- if .OSType -}} +{{- .OSType -}} +{{- else -}} +{{ print "linux" }} +{{- end -}}/ +{{- if eq .Architecture "aarch64" -}} arm64 {{- else -}} amd64 @@ -84,7 +90,7 @@ $(binfile): $(GOFILES) GOARCH=$(GOARCH) \ go build -o $(binfile) \ -ldflags '$(LDFLAGS)' \ - -ldflags '-X github.com/mendersoftware/mender-server/pkg/version.version=$(VERSION)' \ + -ldflags '-X "github.com/mendersoftware/mender-server/pkg/version.version=$(VERSION)"' \ $(BUILDFLAGS) .PHONY: build diff --git a/backend/tests/Dockerfile.integration b/backend/tests/Dockerfile.integration index 42bbb278..55b0fb74 100644 --- a/backend/tests/Dockerfile.integration +++ b/backend/tests/Dockerfile.integration @@ -16,4 +16,5 @@ COPY requirements-integration.txt . RUN pip3 install -r requirements-integration.txt -ENTRYPOINT ["bash", "/tests/run.sh"] +WORKDIR /tests +CMD ["pytest"] diff --git a/backend/tests/docker-compose.yml b/backend/tests/docker-compose.yml index 65c5cfcd..e3a73b56 100644 --- a/backend/tests/docker-compose.yml +++ b/backend/tests/docker-compose.yml @@ -4,7 +4,7 @@ include: services: acceptance-tester: scale: 0 - image: "${CI_REGISTRY_IMAGE:-localhost/backend-tester}:${CI_ACCEPTANCE_IMAGE_TAG:-acceptance}" + image: "${CI_REGISTRY_IMAGE:-localhost/backend-tester}/acceptance:${CI_COMMIT_REF_NAME:-acceptance}" build: dockerfile: Dockerfile.acceptance volumes: @@ -22,15 +22,14 @@ services: integration-tester: scale: 0 - image: "${CI_REGISTRY_IMAGE:-localhost/backend-tester}:${CI_INTEGRATION_IMAGE_TAG:-integration}" + image: "${CI_REGISTRY_IMAGE:-localhost/backend-tester}/integration:${CI_COMMIT_REF_NAME:-integration}" build: dockerfile: Dockerfile.integration volumes: - - ${MENDER_SERVER_PATH:-../../}/backend/tests/integration/docs:/docs - ${MENDER_SERVER_PATH:-../../}/backend/tests/integration/downloaded-tools/mender-artifact:/usr/local/bin/mender-artifact - - ${MENDER_SERVER_PATH:-../../}/backend/tests/integration/tests:/tests + - ${MENDER_SERVER_PATH:-../../}/backend/tests/integration:/tests - /var/run/docker.sock:/var/run/docker.sock - command: ${PYTEST_ARGS} + command: pytest ${PYTEST_ARGS} environment: PYTHONPATH: "/tests" PYTHONDONTWRITEBYTECODE: 1 diff --git a/backend/tests/integration/ci-gitlab-parallel-pytest.py b/backend/tests/integration/ci-gitlab-parallel-pytest.py new file mode 100755 index 00000000..5810e5dc --- /dev/null +++ b/backend/tests/integration/ci-gitlab-parallel-pytest.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python +# Copyright 2024 Northern.tech AS +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# A simple script for praparing command line arguments for splitting +# pytest classes into a Gitlab Parallel matrix. + +import os +import re +import subprocess +import sys + +INDEX = int(os.environ.get("CI_NODE_INDEX", "1")) +TOTAL = int(os.environ.get("CI_NODE_TOTAL", "1")) + +output = subprocess.check_output(["pytest", "--co", "tests"] + sys.argv[1:]) + +classes = [] +expr = re.compile("]+)>") +for line in output.decode("UTF-8").splitlines(): + match = expr.search(line) + if match: + classes.append(match.group(1)) +classes.sort() + + +n_batch = len(classes) // TOTAL +n_rest = len(classes) % TOTAL + +offset = n_batch * (INDEX - 1) +if INDEX <= n_rest: + n_batch += 1 + offset += INDEX +else: + offset += n_rest + +print(" or ".join(classes[offset : offset + n_batch]), end="") diff --git a/backend/tests/integration/run b/backend/tests/integration/run index a0afc3e9..0a136e6c 100755 --- a/backend/tests/integration/run +++ b/backend/tests/integration/run @@ -183,17 +183,27 @@ prepare_pytest_args() { if [ "$val" == "-k" ]; then filter="next" elif [ "$filter" == "next" ]; then - PYTEST_FILTER="$PYTEST_FILTER and $val" + PYTEST_FILTER="$PYTEST_FILTER and ( $val )" filter="done" else PYTEST_ARGS="$PYTEST_ARGS $val" fi done + if test $CI_NODE_TOTAL -gt 1 && test $CI_NODE_INDEX -gt 0; then + # Rewrite the pytest filter into the current node's batch. + PYTEST_FILTER=$(compose_cmd run --rm -it \ + $RUN_ARGS \ + -e CI_NODE_TOTAL=$CI_NODE_TOTAL \ + -e CI_NODE_INDEX=$CI_NODE_INDEX \ + -v "$MENDER_SERVER_PATH/backend/tests/integration/ci-gitlab-parallel-pytest.py:/ci-gitlab-parallel-pytest.py" \ + --entrypoint=/ci-gitlab-parallel-pytest.py \ + integration-tester -k "$PYTEST_FILTER") + fi echo "-- using PYTEST_FILTER=$PYTEST_FILTER" - PYTEST_ARGS="$PYTEST_ARGS -k '$PYTEST_FILTER' $PYTEST_REPORT" - + PYTEST_ARGS="$PYTEST_ARGS -k '${PYTEST_FILTER# }' $PYTEST_REPORT" export PYTEST_ARGS + echo "-- using PYTEST_ARGS=$PYTEST_ARGS" } cleanup() { diff --git a/backend/tests/integration/tests/testutils/__init__.py b/backend/tests/integration/testutils/__init__.py similarity index 100% rename from backend/tests/integration/tests/testutils/__init__.py rename to backend/tests/integration/testutils/__init__.py diff --git a/backend/tests/integration/tests/testutils/api/__init__.py b/backend/tests/integration/testutils/api/__init__.py similarity index 100% rename from backend/tests/integration/tests/testutils/api/__init__.py rename to backend/tests/integration/testutils/api/__init__.py diff --git a/backend/tests/integration/tests/testutils/api/auditlogs.py b/backend/tests/integration/testutils/api/auditlogs.py similarity index 100% rename from backend/tests/integration/tests/testutils/api/auditlogs.py rename to backend/tests/integration/testutils/api/auditlogs.py diff --git a/backend/tests/integration/tests/testutils/api/client.py b/backend/tests/integration/testutils/api/client.py similarity index 100% rename from backend/tests/integration/tests/testutils/api/client.py rename to backend/tests/integration/testutils/api/client.py diff --git a/backend/tests/integration/tests/testutils/api/deployments.py b/backend/tests/integration/testutils/api/deployments.py similarity index 100% rename from backend/tests/integration/tests/testutils/api/deployments.py rename to backend/tests/integration/testutils/api/deployments.py diff --git a/backend/tests/integration/tests/testutils/api/deployments_v2.py b/backend/tests/integration/testutils/api/deployments_v2.py similarity index 100% rename from backend/tests/integration/tests/testutils/api/deployments_v2.py rename to backend/tests/integration/testutils/api/deployments_v2.py diff --git a/backend/tests/integration/tests/testutils/api/deviceauth.py b/backend/tests/integration/testutils/api/deviceauth.py similarity index 100% rename from backend/tests/integration/tests/testutils/api/deviceauth.py rename to backend/tests/integration/testutils/api/deviceauth.py diff --git a/backend/tests/integration/tests/testutils/api/deviceconfig.py b/backend/tests/integration/testutils/api/deviceconfig.py similarity index 100% rename from backend/tests/integration/tests/testutils/api/deviceconfig.py rename to backend/tests/integration/testutils/api/deviceconfig.py diff --git a/backend/tests/integration/tests/testutils/api/deviceconnect.py b/backend/tests/integration/testutils/api/deviceconnect.py similarity index 100% rename from backend/tests/integration/tests/testutils/api/deviceconnect.py rename to backend/tests/integration/testutils/api/deviceconnect.py diff --git a/backend/tests/integration/tests/testutils/api/devicemonitor.py b/backend/tests/integration/testutils/api/devicemonitor.py similarity index 100% rename from backend/tests/integration/tests/testutils/api/devicemonitor.py rename to backend/tests/integration/testutils/api/devicemonitor.py diff --git a/backend/tests/integration/tests/testutils/api/inventory.py b/backend/tests/integration/testutils/api/inventory.py similarity index 100% rename from backend/tests/integration/tests/testutils/api/inventory.py rename to backend/tests/integration/testutils/api/inventory.py diff --git a/backend/tests/integration/tests/testutils/api/inventory_v2.py b/backend/tests/integration/testutils/api/inventory_v2.py similarity index 100% rename from backend/tests/integration/tests/testutils/api/inventory_v2.py rename to backend/tests/integration/testutils/api/inventory_v2.py diff --git a/backend/tests/integration/tests/testutils/api/iot_manager.py b/backend/tests/integration/testutils/api/iot_manager.py similarity index 100% rename from backend/tests/integration/tests/testutils/api/iot_manager.py rename to backend/tests/integration/testutils/api/iot_manager.py diff --git a/backend/tests/integration/tests/testutils/api/proto_shell.py b/backend/tests/integration/testutils/api/proto_shell.py similarity index 100% rename from backend/tests/integration/tests/testutils/api/proto_shell.py rename to backend/tests/integration/testutils/api/proto_shell.py diff --git a/backend/tests/integration/tests/testutils/api/protomsg.py b/backend/tests/integration/testutils/api/protomsg.py similarity index 100% rename from backend/tests/integration/tests/testutils/api/protomsg.py rename to backend/tests/integration/testutils/api/protomsg.py diff --git a/backend/tests/integration/tests/testutils/api/tenantadm.py b/backend/tests/integration/testutils/api/tenantadm.py similarity index 100% rename from backend/tests/integration/tests/testutils/api/tenantadm.py rename to backend/tests/integration/testutils/api/tenantadm.py diff --git a/backend/tests/integration/tests/testutils/api/tenantadm_v2.py b/backend/tests/integration/testutils/api/tenantadm_v2.py similarity index 100% rename from backend/tests/integration/tests/testutils/api/tenantadm_v2.py rename to backend/tests/integration/testutils/api/tenantadm_v2.py diff --git a/backend/tests/integration/tests/testutils/api/useradm.py b/backend/tests/integration/testutils/api/useradm.py similarity index 100% rename from backend/tests/integration/tests/testutils/api/useradm.py rename to backend/tests/integration/testutils/api/useradm.py diff --git a/backend/tests/integration/tests/testutils/api/workflows.py b/backend/tests/integration/testutils/api/workflows.py similarity index 100% rename from backend/tests/integration/tests/testutils/api/workflows.py rename to backend/tests/integration/testutils/api/workflows.py diff --git a/backend/tests/integration/tests/testutils/common.py b/backend/tests/integration/testutils/common.py similarity index 100% rename from backend/tests/integration/tests/testutils/common.py rename to backend/tests/integration/testutils/common.py diff --git a/backend/tests/integration/tests/testutils/infra/__init__.py b/backend/tests/integration/testutils/infra/__init__.py similarity index 100% rename from backend/tests/integration/tests/testutils/infra/__init__.py rename to backend/tests/integration/testutils/infra/__init__.py diff --git a/backend/tests/integration/tests/testutils/infra/cli.py b/backend/tests/integration/testutils/infra/cli.py similarity index 100% rename from backend/tests/integration/tests/testutils/infra/cli.py rename to backend/tests/integration/testutils/infra/cli.py diff --git a/backend/tests/integration/tests/testutils/infra/container_manager/__init__.py b/backend/tests/integration/testutils/infra/container_manager/__init__.py similarity index 100% rename from backend/tests/integration/tests/testutils/infra/container_manager/__init__.py rename to backend/tests/integration/testutils/infra/container_manager/__init__.py diff --git a/backend/tests/integration/tests/testutils/infra/container_manager/base.py b/backend/tests/integration/testutils/infra/container_manager/base.py similarity index 100% rename from backend/tests/integration/tests/testutils/infra/container_manager/base.py rename to backend/tests/integration/testutils/infra/container_manager/base.py diff --git a/backend/tests/integration/tests/testutils/infra/container_manager/docker_compose_base_manager.py b/backend/tests/integration/testutils/infra/container_manager/docker_compose_base_manager.py similarity index 100% rename from backend/tests/integration/tests/testutils/infra/container_manager/docker_compose_base_manager.py rename to backend/tests/integration/testutils/infra/container_manager/docker_compose_base_manager.py diff --git a/backend/tests/integration/tests/testutils/infra/container_manager/docker_compose_manager.py b/backend/tests/integration/testutils/infra/container_manager/docker_compose_manager.py similarity index 100% rename from backend/tests/integration/tests/testutils/infra/container_manager/docker_compose_manager.py rename to backend/tests/integration/testutils/infra/container_manager/docker_compose_manager.py diff --git a/backend/tests/integration/tests/testutils/infra/container_manager/docker_manager.py b/backend/tests/integration/testutils/infra/container_manager/docker_manager.py similarity index 100% rename from backend/tests/integration/tests/testutils/infra/container_manager/docker_manager.py rename to backend/tests/integration/testutils/infra/container_manager/docker_manager.py diff --git a/backend/tests/integration/tests/testutils/infra/container_manager/factory.py b/backend/tests/integration/testutils/infra/container_manager/factory.py similarity index 100% rename from backend/tests/integration/tests/testutils/infra/container_manager/factory.py rename to backend/tests/integration/testutils/infra/container_manager/factory.py diff --git a/backend/tests/integration/tests/testutils/infra/container_manager/kubernetes_manager.py b/backend/tests/integration/testutils/infra/container_manager/kubernetes_manager.py similarity index 100% rename from backend/tests/integration/tests/testutils/infra/container_manager/kubernetes_manager.py rename to backend/tests/integration/testutils/infra/container_manager/kubernetes_manager.py diff --git a/backend/tests/integration/tests/testutils/infra/device.py b/backend/tests/integration/testutils/infra/device.py similarity index 100% rename from backend/tests/integration/tests/testutils/infra/device.py rename to backend/tests/integration/testutils/infra/device.py diff --git a/backend/tests/integration/tests/testutils/infra/mongo.py b/backend/tests/integration/testutils/infra/mongo.py similarity index 100% rename from backend/tests/integration/tests/testutils/infra/mongo.py rename to backend/tests/integration/testutils/infra/mongo.py diff --git a/backend/tests/integration/tests/testutils/infra/smtpd_mock.py b/backend/tests/integration/testutils/infra/smtpd_mock.py similarity index 100% rename from backend/tests/integration/tests/testutils/infra/smtpd_mock.py rename to backend/tests/integration/testutils/infra/smtpd_mock.py diff --git a/backend/tests/integration/tests/testutils/integration/stripe.py b/backend/tests/integration/testutils/integration/stripe.py similarity index 100% rename from backend/tests/integration/tests/testutils/integration/stripe.py rename to backend/tests/integration/testutils/integration/stripe.py diff --git a/backend/tests/integration/tests/testutils/util/__init__.py b/backend/tests/integration/testutils/util/__init__.py similarity index 100% rename from backend/tests/integration/tests/testutils/util/__init__.py rename to backend/tests/integration/testutils/util/__init__.py diff --git a/backend/tests/integration/tests/testutils/util/artifact.py b/backend/tests/integration/testutils/util/artifact.py similarity index 100% rename from backend/tests/integration/tests/testutils/util/artifact.py rename to backend/tests/integration/testutils/util/artifact.py diff --git a/backend/tests/integration/tests/testutils/util/crypto.py b/backend/tests/integration/testutils/util/crypto.py similarity index 100% rename from backend/tests/integration/tests/testutils/util/crypto.py rename to backend/tests/integration/testutils/util/crypto.py diff --git a/backend/tests/integration/tests/testutils/util/websockets.py b/backend/tests/integration/testutils/util/websockets.py similarity index 100% rename from backend/tests/integration/tests/testutils/util/websockets.py rename to backend/tests/integration/testutils/util/websockets.py