# These templates do the following: # python.yml: # - creates a venv and installs dev dependencies # - configures git username and email for unit tests # - sets python jobs to only run when a .py file is edited # javascript.yml: # - performs npm install based on the provided image and path # - sets javascript jobs to only run when a .js or .vue # file is edited include: - project: 'openflexure/ci-templates' file: '/python.yml' - project: 'openflexure/ci-templates' file: '/javascript.yml' # We are using this job to pass the image name, path, # and cache path to the javascript template job .javascript_webapp: extends: .javascript variables: JS_IMAGE: node:18 JS_PATH: webapp JS_CACHE_PATH: webapp/node_modules # Collects together common trigger rules for # reusability .rules_common: rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event" - if: $CI_PIPELINE_SOURCE == "push" - if: $CI_COMMIT_TAG - if: $CI_PIPELINE_SOURCE == "web" - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH - when: never stages: - prepare - analysis - testing - build - integration - package - deploy # Only runs when .meta/Dockerfile is edited meta-build-image: image: docker:stable services: - docker:dind stage: prepare script: - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY - cd .meta-testimage-python - docker build -t $CI_REGISTRY/openflexure/openflexure-microscope-server/testimage-python:latest . - docker push $CI_REGISTRY/openflexure/openflexure-microscope-server/testimage-python:latest rules: - if: $CI_COMMIT_REF_NAME == "v3" changes: - .meta/Dockerfile # Check webapp and server have matching version string version-check: stage: analysis extends: .rules_common #use a base python image as nothing needs to be installed image: python:3.11 script: - ./check_version_sync.py # A job to protect reviewers from Julian's terrible spelling. spelling: stage: analysis extends: - .python # Extending this job means that the rules section defined # in .rules_common overwrites any rules defined in .python - .rules_common script: - codespell . # Python static analysis and formatting with ruff # Only runs when a .py file is edited ruff-checks: stage: analysis extends: .python script: - ruff check - ruff format --check # Only run on changed python files # Python type checking with Mypy # Only runs when a .py file is edited mypy: stage: analysis extends: .python script: - mkdir -p mypy # "|| true" is used for preventing job failure when mypy find errors - mypy src --cobertura-xml-report mypy --no-error-summary > mypy-out.txt || true - mypy-gitlab-code-quality < mypy-out.txt > codequality.json allow_failure: true artifacts: reports: codequality: codequality.json coverage_report: coverage_format: cobertura path: mypy/cobertura.xml # Python unit tests with PyTest # Only runs when a .py file is edited pytest: stage: testing extends: .python script: - pytest - mv .coverage .coverage.main # --gitlab-code-quality-report=pytest-warnings.json # can restore when it installs ok artifacts: when: always paths: - report.xml - .coverage.main # Combine CI coverage with coverage from Picamera # Only runs when a .py file is edited combined-tests: stage: testing extends: .python needs: - job: pytest artifacts: true script: - ./picamera_tests.py unzip - coverage combine # Use -i to ignore file changing between the two runs. We check the relevant ones. - coverage report -i - coverage xml -i coverage: '/(?i)total.*? (100(?:\.0+)?\%|[1-9]?\d(?:\.\d+)?\%)$/' artifacts: when: always reports: junit: report.xml coverage_report: coverage_format: cobertura path: coverage.xml # JavaScript linting with ESLint (via Vue CLI) # Only runs when a .js or .vue file is edited eslint: stage: analysis extends: .javascript_webapp script: # Build JS application for production - npm run lint # Build JS app build: stage: build extends: - .javascript_webapp - .rules_common script: # Build JS application for production - npm run build artifacts: name: "dist" expire_in: 1 week paths: - "src/openflexure_microscope_server/static/" # Only runs when a .py file is edited unless the commit branch is V3 build-docs: extends: .python stage: build script: - | pydoctor -W \ --docformat restructuredtext \ --project-name "OpenFlexure Microscope Server" \ --project-version $CI_COMMIT_REF_NAME \ --theme readthedocs \ --html-viewsource-base https://gitlab.com/openflexure/openflexure-microscope-server/-/tree/$CI_COMMIT_SHA/ \ src/openflexure_microscope_server - echo "JOB_ID=$CI_JOB_ID" > build-docs.env artifacts: expire_in: 1 week name: "${CI_PROJECT_NAME}-${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHORT_SHA}-docs" paths: - apidocs reports: dotenv: build-docs.env environment: name: review/$CI_COMMIT_REF_SLUG url: https://$CI_PROJECT_ROOT_NAMESPACE.gitlab.io/-/openflexure-microscope-server/-/jobs/$JOB_ID/artifacts/apidocs/index.html rules: # So that 'pages' job at the end always works # Add new rule first as the rules defined in .python # end in when: never, so if this new rule goes after that # clause, it will never be reached as rules are # evaluated top to bottom - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # This syntax means we append the rules from the .python # job to this job, instead of overwriting them by creating # this new rules section - !reference [.python, rules] # Only runs when a .py file is edited server_integration_tests: extends: .python stage: integration needs: - job: build artifacts: true script: - tests/integration_tests/testfile.py pages: needs: - job: build-docs artifacts: true stage: deploy image: "alpine:latest" script: - mv apidocs public artifacts: paths: - public rules: - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH