Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Is3418/validation with ooil test my/osparc/service #3479

Merged
merged 20 commits into from
Oct 31, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions packages/service-integration/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,29 @@ FROM python:${PYTHON_VERSION}-slim-buster as base

LABEL maintainer=pcrespov

RUN set -eux \
&& apt-get update \
&& apt-get install -y \
git \
&& rm -rf /var/lib/apt/lists/* \
# verify that the binary works
&& git --version

# simcore-user uid=8004(scu) gid=8004(scu) groups=8004(scu)
ENV SC_USER_ID=8004 \
SC_USER_NAME=scu \
SC_BUILD_TARGET=base \
SC_BOOT_MODE=default

RUN adduser \
--uid ${SC_USER_ID} \
--disabled-password \
--gecos "" \
--shell /bin/sh \
--home /home/${SC_USER_NAME} \
${SC_USER_NAME}


# Sets utf-8 encoding for Python et al
ENV LANG=C.UTF-8
# Turns off writing .pyc files; superfluous on an ephemeral container.
Expand Down Expand Up @@ -52,6 +75,8 @@ FROM base as development
# NOTE: this is necessary to allow to build development images but is the same as production here
FROM base as production

USER scu

COPY --from=build --chown=scu:scu ${VIRTUAL_ENV} ${VIRTUAL_ENV}

# NOTE: do not activate ENV PYTHONOPTIMIZE=TRUE since excutable contains pytest code
Expand Down
19 changes: 15 additions & 4 deletions packages/service-integration/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,21 @@ build build-nc: ## [docker] builds docker image of executable w/ or w/o cache
docker run local/${PACKAGE_NAME}:production --version

.PHONY: inspect
inspect:
docker image inspect local/${PACKAGE_NAME}:production | jq '.[0] | .RepoTags, .Config.Labels, .Architecture'
inspect: ## [docker] inspects container
docker image inspect \
local/${PACKAGE_NAME}:production | jq '.[0] | .RepoTags, .Config.Labels, .Architecture'


_src_dir = $(if $(target),$(target),$(PWD))

.PHONY: shell
shell:
docker run -it --entrypoint bash local/${PACKAGE_NAME}:production
shell: ## [docker] opens shell in container
docker run \
-it \
--volume="/etc/group:/etc/group:ro" \
--volume="/etc/passwd:/etc/passwd:ro" \
--user="$(shell id --user "$(USER)")":scu \
--entrypoint bash \
--volume "$(_src_dir)":/src \
--workdir=/src \
local/${PACKAGE_NAME}:production
2 changes: 1 addition & 1 deletion packages/service-integration/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.0.2
1.0.3
6 changes: 3 additions & 3 deletions packages/service-integration/requirements/_base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ docker==6.0.0
# via -r requirements/_base.in
email-validator==1.3.0
# via pydantic
exceptiongroup==1.0.0
# via pytest
idna==3.4
# via
# email-validator
Expand All @@ -42,8 +44,6 @@ packaging==21.3
# pytest
pluggy==1.0.0
# via pytest
py==1.11.0
# via pytest
pydantic==1.10.2
# via
# -c requirements/../../../packages/models-library/requirements/../../../requirements/constraints.txt
Expand All @@ -55,7 +55,7 @@ pyparsing==3.0.9
# via packaging
pyrsistent==0.18.1
# via jsonschema
pytest==7.1.3
pytest==7.2.0
# via -r requirements/_base.in
pyyaml==6.0
# via
Expand Down
10 changes: 5 additions & 5 deletions packages/service-integration/requirements/_test.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ dill==0.3.5.1
# via pylint
docopt==0.6.2
# via coveralls
exceptiongroup==1.0.0
# via
# -c requirements/_base.txt
# pytest
idna==3.4
# via
# -c requirements/_base.txt
Expand All @@ -54,17 +58,13 @@ pluggy==1.0.0
# via
# -c requirements/_base.txt
# pytest
py==1.11.0
# via
# -c requirements/_base.txt
# pytest
pylint==2.15.4
# via -r requirements/_test.in
pyparsing==3.0.9
# via
# -c requirements/_base.txt
# packaging
pytest==7.1.3
pytest==7.2.0
# via
# -c requirements/_base.txt
# -r requirements/_test.in
Expand Down
27 changes: 27 additions & 0 deletions packages/service-integration/scripts/ooil.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/bin/bash
# http://redsymbol.net/articles/unofficial-bash-strict-mode/

set -o errexit
set -o nounset
set -o pipefail
IFS=$'\n\t'


IMAGE_NAME="${DOCKER_REGISTRY:-itisfoundation}/service-integration:${DOCKER_IMAGE_TAG:-master-github-latest}"
WORKDIR="$(pwd)"

run() {
docker run \
-it \
--rm \
--volume="/etc/group:/etc/group:ro" \
--volume="/etc/passwd:/etc/passwd:ro" \
--user="$(id --user "$USER")":"$(id --group "$USER")" \
--volume "$WORKDIR":/src \
--workdir=/src \
"$IMAGE_NAME" \
"$@"
}


run "$@"
2 changes: 1 addition & 1 deletion packages/service-integration/setup.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 1.0.2
current_version = 1.0.3
commit = True
message = service-integration version: {current_version} → {new_version}
tag = False
Expand Down
6 changes: 6 additions & 0 deletions packages/service-integration/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ def read_reqs(reqs_path: Path) -> set[str]:
packages=find_packages(where="src"),
package_dir={"": "src"},
include_package_data=True,
package_data={
"": [
"service/tests/**/*.py",
"service/tests/unit/*.py",
]
},
test_suite="tests",
tests_require=TEST_REQUIREMENTS,
extras_require={},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import typer

from ._meta import __version__
from .commands import compose, config, metadata, run_creator
from .commands import compose, config, metadata, run_creator, test
from .settings import AppSettings

app = typer.Typer()
Expand Down Expand Up @@ -54,6 +54,7 @@ def main(
# new
app.command("compose")(compose.main)
app.command("config")(config.main)
app.command("test")(test.main)
# legacy
app.command("bump-version")(metadata.bump_version)
app.command("get-version")(metadata.get_version)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,19 @@ def _run_git(*args) -> str:
def _run_git_or_empty_string(*args) -> str:
try:
return _run_git(*args)
except FileNotFoundError as err:
error_console.print(
"WARNING: Defaulting label to emtpy string",
"since git is not installed or cannot be executed:",
err,
)
except subprocess.CalledProcessError as err:
error_console.print(
"WARNING: Defaulting label to emtpy string",
"due to:",
err.stderr,
)
return ""
return ""


def create_docker_compose_image_spec(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from pathlib import Path

import rich
import typer

from ..service import pytest_runner


def main(
service_dir: Path = typer.Argument(
..., help="Root directory of the service under test"
),
):
"""Runs tests against service directory"""

if not service_dir.exists():
raise typer.BadParameter("Invalid path to service directory")

rich.print(f"Testing '{service_dir.resolve()}' ...")
error_code = pytest_runner.main(service_dir=service_dir, extra_args=[])
raise typer.Exit(code=error_code)
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import warnings

warnings.warn(
f"{__name__} is deprecated for cookiecutter-osparc-service>0.4.Use directoy test CLI instead."
"See https://github.com/ITISFoundation/cookiecutter-osparc-service/releases/tag/v0.4.0",
DeprecationWarning,
)


def pytest_addoption(parser):
group = parser.getgroup("service-integration")
group.addoption(
"--service-dir",
action="store",
help="Base directory for target service",
)

group.addoption(
"--metadata",
action="store",
help="metadata yaml configuration file",
)
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
# pylint: disable=redefined-outer-name
# pylint: disable=unused-argument
# pylint: disable=unused-variable
import sys
from pathlib import Path

import pytest

current_dir = Path(sys.argv[0] if __name__ == "__main__" else __file__).resolve().parent


@pytest.fixture(scope="session")
def project_slug_dir() -> Path:
raise NotImplementedError("Override fixture 'project_slug_dir' REQUIRED")
def project_slug_dir(request: pytest.FixtureRequest) -> Path:
try:
root_dir = Path(request.config.getoption("--service-dir"))
except TypeError:
pytest.fail("--service-dir is not set")

assert isinstance(root_dir, Path)
assert root_dir.exists()
assert any(root_dir.glob(".osparc"))
return root_dir


@pytest.fixture(scope="session")
Expand All @@ -20,20 +25,6 @@ def project_name(project_slug_dir: Path) -> str:
return project_slug_dir.name


@pytest.fixture(scope="session")
def src_dir(project_slug_dir: Path) -> Path:
_src_dir = project_slug_dir / "src"
assert _src_dir.exists()
return _src_dir


@pytest.fixture(scope="session")
def tests_dir(project_slug_dir: Path) -> Path:
_tests_dir = project_slug_dir / "tests"
assert _tests_dir.exists()
return _tests_dir


@pytest.fixture(scope="session")
def validation_dir(project_slug_dir: Path) -> Path:
validation_dir = project_slug_dir / "validation"
Expand All @@ -42,22 +33,13 @@ def validation_dir(project_slug_dir: Path) -> Path:


@pytest.fixture(scope="session")
def tools_dir(project_slug_dir: Path) -> Path:
tools_dir = project_slug_dir / "tools"
assert tools_dir.exists()
return tools_dir


@pytest.fixture(scope="session")
def docker_dir(project_slug_dir: Path) -> Path:
docker_dir = project_slug_dir / "docker"
assert docker_dir.exists()
return docker_dir

def metadata_file(project_slug_dir: Path, request: pytest.FixtureRequest) -> Path:
try:
metadata_file = Path(request.config.getoption("--metadata"))
except TypeError:
metadata_file = project_slug_dir / "metadata" / "metadata.yml"

@pytest.fixture(scope="session")
def metadata_file(project_slug_dir: Path) -> Path:
metadata_file = project_slug_dir / "metadata" / "metadata.yml"
assert isinstance(metadata_file, Path)
assert metadata_file.exists()
return metadata_file

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import logging
import sys
import tempfile
from pathlib import Path
from typing import Optional

import pytest

CURRENT_DIR = Path(sys.argv[0] if __name__ == "__main__" else __file__).resolve().parent
TESTS_DIR = CURRENT_DIR / "tests"

logger = logging.getLogger(__name__)


def main(
service_dir: Path, *, debug: bool = False, extra_args: Optional[list[str]] = None
) -> int:

pytest_args = [
# global cache options
"--cache-clear",
f"--override-ini=cache_dir={tempfile.gettempdir()}/.pytest_cache__service_integration",
# tests
f"{TESTS_DIR}",
# custom options
f"--service-under-test-dir={service_dir}",
]

if debug:
pytest_args += ["-vv", "--log-level=DEBUG", "--pdb"]

if extra_args:
pytest_args += extra_args

logger.debug("Running 'pytest %s'", " ".join(pytest_args))
exit_code = pytest.main(pytest_args)
logger.debug("exit with code=%d", exit_code)
return exit_code


if __name__ == "__main__":
# Entrypoint for stand-alone 'service_integration/service' package
sys.exit(
main(
service_dir=Path(sys.argv[1]),
extra_args=sys.argv[2:],
)
)
Loading