# This file is a template, and might need editing before it works on your project. # Official language image. Look for the different tagged releases at: # https://hub.docker.com/r/library/python/tags/ image: $CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX/python:3.11 #commands to run in the Docker container before starting each job. variables: DOCKER_TLS_CERTDIR: "" BEC_CORE_BRANCH: "main" OPHYD_DEVICES_BRANCH: "main" CHILD_PIPELINE_BRANCH: $CI_DEFAULT_BRANCH workflow: rules: - if: $CI_PIPELINE_SOURCE == "schedule" - if: $CI_PIPELINE_SOURCE == "web" - if: $CI_PIPELINE_SOURCE == "pipeline" - if: $CI_PIPELINE_SOURCE == "parent_pipeline" - if: $CI_PIPELINE_SOURCE == "merge_request_event" - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS when: never - if: $CI_COMMIT_BRANCH include: - template: Security/Secret-Detection.gitlab-ci.yml - project: "bec/awi_utils" file: "/templates/check-packages-job.yml" inputs: stage: test path: "." pytest_args: "-v --random-order tests/" exclude_packages: "" # different stages in the pipeline stages: - Formatter - test - AdditionalTests - End2End - Deploy .install-qt-webengine-deps: &install-qt-webengine-deps - apt-get -y install libnss3 libxdamage1 libasound2 libatomic1 libxcursor1 - export QTWEBENGINE_DISABLE_SANDBOX=1 .clone-repos: &clone-repos - git clone --branch $BEC_CORE_BRANCH https://gitlab.psi.ch/bec/bec.git - git clone --branch $OPHYD_DEVICES_BRANCH https://gitlab.psi.ch/bec/ophyd_devices.git - export OHPYD_DEVICES_PATH=$PWD/ophyd_devices .install-os-packages: &install-os-packages - apt-get update - apt-get install -y libgl1-mesa-glx libegl1-mesa x11-utils libxkbcommon-x11-0 libdbus-1-3 - *install-qt-webengine-deps before_script: - if [[ "$CI_PROJECT_PATH" != "bec/bec_widgets" ]]; then echo -e "\033[35;1m Using branch $CHILD_PIPELINE_BRANCH of BEC Widgets \033[0;m"; test -d bec_widgets || git clone --branch $CHILD_PIPELINE_BRANCH https://gitlab.psi.ch/bec/bec_widgets.git; cd bec_widgets; fi formatter: stage: Formatter needs: [] script: - pip install black isort - isort --check --diff ./ - black --check --diff --color ./ rules: - if: $CI_PROJECT_PATH == "bec/bec_widgets" pylint: stage: Formatter needs: [] before_script: - pip install pylint pylint-exit anybadge - pip install -e .[dev,pyqt6] script: - mkdir ./pylint - pylint ./bec_widgets --output-format=text --output=./pylint/pylint.log | tee ./pylint/pylint.log || pylint-exit $? - PYLINT_SCORE=$(sed -n 's/^Your code has been rated at \([-0-9.]*\)\/.*/\1/p' ./pylint/pylint.log) - anybadge --label=Pylint --file=pylint/pylint.svg --value=$PYLINT_SCORE 2=red 4=orange 8=yellow 10=green - echo "Pylint score is $PYLINT_SCORE" artifacts: paths: - ./pylint/ expire_in: 1 week rules: - if: $CI_PROJECT_PATH == "bec/bec_widgets" pylint-check: stage: Formatter needs: [] allow_failure: true before_script: - pip install pylint pylint-exit anybadge - apt-get update - apt-get install -y bc script: - git fetch origin $CI_MERGE_REQUEST_TARGET_BRANCH_NAME # Identify changed Python files - if [ "$CI_PIPELINE_SOURCE" == "merge_request_event" ]; then TARGET_BRANCH_COMMIT_SHA=$(git rev-parse origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME); CHANGED_FILES=$(git diff --name-only $TARGET_BRANCH_COMMIT_SHA HEAD | grep '\.py$' || true); else CHANGED_FILES=$(git diff --name-only $CI_COMMIT_BEFORE_SHA $CI_COMMIT_SHA | grep '\.py$' || true); fi - if [ -z "$CHANGED_FILES" ]; then echo "No Python files changed."; exit 0; fi - echo "Changed Python files:" - $CHANGED_FILES # Run pylint only on changed files - mkdir ./pylint - pylint $CHANGED_FILES --output-format=text | tee ./pylint/pylint_changed_files.log || pylint-exit $? - PYLINT_SCORE=$(sed -n 's/^Your code has been rated at \([-0-9.]*\)\/.*/\1/p' ./pylint/pylint_changed_files.log) - echo "Pylint score is $PYLINT_SCORE" # Fail the job if the pylint score is below 9 - if [ "$(echo "$PYLINT_SCORE < 9" | bc)" -eq 1 ]; then echo "Your pylint score is below the acceptable threshold (9)."; exit 1; fi artifacts: paths: - ./pylint/ expire_in: 1 week rules: - if: $CI_PROJECT_PATH == "bec/bec_widgets" tests: stage: test needs: [] variables: QT_QPA_PLATFORM: "offscreen" script: - *clone-repos - *install-os-packages - pip install -e ./bec/bec_lib[dev] - pip install -e ./bec/bec_ipython_client - pip install -e .[dev,pyqt6] - coverage run --source=./bec_widgets -m pytest -v --junitxml=report.xml --random-order --full-trace ./tests/unit_tests - coverage report - coverage xml coverage: '/(?i)total.*? (100(?:\.0+)?\%|[1-9]?\d(?:\.\d+)?\%)$/' artifacts: reports: junit: report.xml coverage_report: coverage_format: cobertura path: coverage.xml test-matrix: parallel: matrix: - PYTHON_VERSION: - "3.10" - "3.11" - "3.12" QT_PCKG: - "pyside6" - "pyqt5" - "pyqt6" stage: AdditionalTests needs: [] variables: QT_QPA_PLATFORM: "offscreen" PYTHON_VERSION: "" QT_PCKG: "" image: $CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX/python:$PYTHON_VERSION script: - *clone-repos - *install-os-packages - pip install -e ./bec/bec_lib[dev] - pip install -e ./bec/bec_ipython_client - pip install -e .[dev,$QT_PCKG] - pytest -v --junitxml=report.xml --random-order ./tests/unit_tests allow_failure: true end-2-end-conda: stage: End2End needs: [] image: continuumio/miniconda3 allow_failure: false variables: QT_QPA_PLATFORM: "offscreen" script: - *clone-repos - *install-os-packages - conda config --prepend channels conda-forge - conda config --set channel_priority strict - conda config --set always_yes yes --set changeps1 no - conda create -q -n test-environment python=3.11 - conda init bash - source ~/.bashrc - conda activate test-environment - cd ./bec - source ./bin/install_bec_dev.sh -t - pip install -e ./bec_lib[dev] - pip install -e ./bec_ipython_client[dev] - cd ../ - pip install -e .[dev,pyqt6] - cd ./tests/end-2-end - pytest -v --start-servers --flush-redis --random-order artifacts: when: on_failure paths: - ./logs/*.log expire_in: 1 week rules: - if: '$CI_PIPELINE_SOURCE == "schedule"' - if: '$CI_PIPELINE_SOURCE == "web"' - if: '$CI_PIPELINE_SOURCE == "pipeline"' - if: '$CI_PIPELINE_SOURCE == "parent_pipeline"' - if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "main"' - if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "production"' semver: stage: Deploy needs: ["tests"] script: - git config --global user.name "ci_update_bot" - git config --global user.email "ci_update_bot@bec.ch" - git checkout "$CI_COMMIT_REF_NAME" - git reset --hard origin/"$CI_COMMIT_REF_NAME" # delete all local tags - git tag -l | xargs git tag -d - git fetch --tags - git tag # build and publish package - pip install python-semantic-release==9.* wheel build twine - export GL_TOKEN=$CI_UPDATES - semantic-release -vv version # check if any artifacts were created - if [ ! -d dist ]; then echo No release will be made; exit 0; fi - twine upload dist/* -u __token__ -p $CI_PYPI_TOKEN --skip-existing - semantic-release publish allow_failure: false rules: - if: '$CI_COMMIT_REF_NAME == "main" && $CI_PROJECT_PATH == "bec/bec_widgets"' pages: stage: Deploy needs: ["semver"] variables: TARGET_BRANCH: $CI_COMMIT_REF_NAME rules: - if: "$CI_COMMIT_TAG != null" variables: TARGET_BRANCH: $CI_COMMIT_TAG - if: '$CI_COMMIT_REF_NAME == "main" && $CI_PROJECT_PATH == "bec/bec_widgets"' script: - curl -X POST -d "branches=$CI_COMMIT_REF_NAME" -d "token=$RTD_TOKEN" https://readthedocs.org/api/v2/webhook/bec-widgets/253243/