Loading .gitlab-ci.pre-commit-run.bash 0 → 100644 +58 −0 Original line number Diff line number Diff line # Find a suitable commit for determining changed files # # # Copyright 2022 Dom Sekotill <dom.sekotill@kodo.org.uk> # # 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. pre_commit_run() ( set -eu declare -a PRE_COMMIT_ARGS find_lca() { local repo=$CI_REPOSITORY_URL local current_branch=$1 other_branch=$2 # See https://stackoverflow.com/questions/63878612/git-fatal-error-in-object-unshallow-sha-1 # and https://stackoverflow.com/questions/4698759/converting-git-repository-to-shallow/53245223#53245223 # for background on what `git repack -d` is doing here. git repack -qd git fetch -q $repo --shallow-exclude=$other_branch $current_branch git fetch -q $repo --deepen=1 $current_branch FROM_REF=$(git rev-parse -q --revs-only --verify shallow) || unset FROM_REF } fetch_ref() { git fetch -q $CI_REPOSITORY_URL --depth=1 $1 FROM_REF=$1 } if [[ -v CI_COMMIT_BEFORE_SHA ]] && [[ ! $CI_COMMIT_BEFORE_SHA =~ ^0{40}$ ]]; then fetch_ref $CI_COMMIT_BEFORE_SHA elif [[ -v CI_MERGE_REQUEST_TARGET_BRANCH_NAME ]]; then find_lca $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME $CI_MERGE_REQUEST_TARGET_BRANCH_NAME elif [[ -v CI_COMMIT_BRANCH ]] && [[ $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH ]]; then find_lca $CI_COMMIT_BRANCH $CI_DEFAULT_BRANCH fi if [[ -v FROM_REF ]]; then PRE_COMMIT_ARGS=( --from-ref=$FROM_REF --to-ref=$CI_COMMIT_SHA ) else PRE_COMMIT_ARGS=( --all-files ) fi pre-commit run "$@" "${PRE_COMMIT_ARGS[@]}" ) .gitlab-ci.yml 0 → 100644 +153 −0 Original line number Diff line number Diff line # Optional project CI variables to set: # # SAFETY_API_KEY: # Set to your API key for accessing up-to-date package security information workflow: rules: - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS when: never - if: $CI_PIPELINE_SOURCE == "merge_request_event" - if: $CI_COMMIT_TAG =~ /^v[0-9]/ - if: $CI_COMMIT_BRANCH .python: image: python:3.10 variables: PIP_CACHE_DIR: $CI_PROJECT_DIR/cache/pkg PIP_NO_COMPILE: "true" PIP_NO_CLEAN: "true" cache: key: $CI_JOB_IMAGE paths: [cache] Quality Gate: stage: .pre image: docker.kodo.org.uk/ci-images/pre-commit:latest variables: PRE_COMMIT_HOME: $CI_PROJECT_DIR/cache/pre-commit cache: key: $CI_JOB_IMAGE paths: [cache] rules: - if: $CI_PIPELINE_SOURCE == "push" - if: $CI_PIPELINE_SOURCE == "merge_request_event" script: - source .gitlab-ci.pre-commit-run.bash - pre_commit_run --hook-stage=commit - pre_commit_run --hook-stage=push Build Package: stage: build extends: [.python] script: - pip install build - python -m build artifacts: paths: [dist] Pin: # Pin dependencies in requirements.txt for reproducing pipeline results stage: test extends: [.python] script: - pip install --prefer-binary -e . - pip freeze --exclude-editable | tee requirements.txt artifacts: paths: [requirements.txt] Dependency Check: stage: test image: pyupio/safety:latest needs: [Pin] allow_failure: true script: - safety check -r requirements.txt Unit Tests: stage: test extends: [.python] needs: [Pin] script: - pip install -r requirements.txt -e .[tests] pytest - coverage run -m pytest tests --verbose --junit-xml=results/xunit.xml after_script: - coverage report - coverage json - coverage xml - coverage html coverage: '/^TOTAL .* (\d{1,3}\.\d{2})%$/' artifacts: paths: [results] reports: junit: results/xunit.xml coverage_report: coverage_format: cobertura path: results/coverage.xml Check Tag: stage: test extends: [.python] needs: ["Build Package"] rules: - if: $CI_COMMIT_TAG script: - pip install packaging pkginfo - | python <<-END from glob import glob from packaging.version import Version from pkginfo import Wheel wheel_path = glob("dist/*.whl")[0] wheel = Wheel(wheel_path) assert Version("$CI_COMMIT_TAG") == Version(wheel.version) END Upload Package: stage: deploy extends: [.python] needs: ["Build Package"] rules: - if: $CI_COMMIT_TAG script: - pip install twine - TWINE_USERNAME=gitlab-ci-token TWINE_PASSWORD=$CI_JOB_TOKEN twine upload --verbose --non-interactive --repository-url $CI_API_V4_URL/projects/$CI_PROJECT_ID/packages/pypi dist/* Documentation: stage: build extends: [.python] script: - pip install .[docs] - make -C doc html HTML_BUILDER=dirhtml BUILDDIR=../build artifacts: paths: [build] pages: stage: deploy needs: [Documentation] rules: - if: $CI_COMMIT_TAG script: - mv build/html public artifacts: paths: [public] pyproject.toml +3 −0 Original line number Diff line number Diff line Loading @@ -83,6 +83,9 @@ disallow_any_explicit = true # disallow_any_expr = true [tool.pytest.ini_options] python_classes = "" [tool.coverage.run] data_file = "results/coverage.db" branch = true Loading Loading
.gitlab-ci.pre-commit-run.bash 0 → 100644 +58 −0 Original line number Diff line number Diff line # Find a suitable commit for determining changed files # # # Copyright 2022 Dom Sekotill <dom.sekotill@kodo.org.uk> # # 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. pre_commit_run() ( set -eu declare -a PRE_COMMIT_ARGS find_lca() { local repo=$CI_REPOSITORY_URL local current_branch=$1 other_branch=$2 # See https://stackoverflow.com/questions/63878612/git-fatal-error-in-object-unshallow-sha-1 # and https://stackoverflow.com/questions/4698759/converting-git-repository-to-shallow/53245223#53245223 # for background on what `git repack -d` is doing here. git repack -qd git fetch -q $repo --shallow-exclude=$other_branch $current_branch git fetch -q $repo --deepen=1 $current_branch FROM_REF=$(git rev-parse -q --revs-only --verify shallow) || unset FROM_REF } fetch_ref() { git fetch -q $CI_REPOSITORY_URL --depth=1 $1 FROM_REF=$1 } if [[ -v CI_COMMIT_BEFORE_SHA ]] && [[ ! $CI_COMMIT_BEFORE_SHA =~ ^0{40}$ ]]; then fetch_ref $CI_COMMIT_BEFORE_SHA elif [[ -v CI_MERGE_REQUEST_TARGET_BRANCH_NAME ]]; then find_lca $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME $CI_MERGE_REQUEST_TARGET_BRANCH_NAME elif [[ -v CI_COMMIT_BRANCH ]] && [[ $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH ]]; then find_lca $CI_COMMIT_BRANCH $CI_DEFAULT_BRANCH fi if [[ -v FROM_REF ]]; then PRE_COMMIT_ARGS=( --from-ref=$FROM_REF --to-ref=$CI_COMMIT_SHA ) else PRE_COMMIT_ARGS=( --all-files ) fi pre-commit run "$@" "${PRE_COMMIT_ARGS[@]}" )
.gitlab-ci.yml 0 → 100644 +153 −0 Original line number Diff line number Diff line # Optional project CI variables to set: # # SAFETY_API_KEY: # Set to your API key for accessing up-to-date package security information workflow: rules: - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS when: never - if: $CI_PIPELINE_SOURCE == "merge_request_event" - if: $CI_COMMIT_TAG =~ /^v[0-9]/ - if: $CI_COMMIT_BRANCH .python: image: python:3.10 variables: PIP_CACHE_DIR: $CI_PROJECT_DIR/cache/pkg PIP_NO_COMPILE: "true" PIP_NO_CLEAN: "true" cache: key: $CI_JOB_IMAGE paths: [cache] Quality Gate: stage: .pre image: docker.kodo.org.uk/ci-images/pre-commit:latest variables: PRE_COMMIT_HOME: $CI_PROJECT_DIR/cache/pre-commit cache: key: $CI_JOB_IMAGE paths: [cache] rules: - if: $CI_PIPELINE_SOURCE == "push" - if: $CI_PIPELINE_SOURCE == "merge_request_event" script: - source .gitlab-ci.pre-commit-run.bash - pre_commit_run --hook-stage=commit - pre_commit_run --hook-stage=push Build Package: stage: build extends: [.python] script: - pip install build - python -m build artifacts: paths: [dist] Pin: # Pin dependencies in requirements.txt for reproducing pipeline results stage: test extends: [.python] script: - pip install --prefer-binary -e . - pip freeze --exclude-editable | tee requirements.txt artifacts: paths: [requirements.txt] Dependency Check: stage: test image: pyupio/safety:latest needs: [Pin] allow_failure: true script: - safety check -r requirements.txt Unit Tests: stage: test extends: [.python] needs: [Pin] script: - pip install -r requirements.txt -e .[tests] pytest - coverage run -m pytest tests --verbose --junit-xml=results/xunit.xml after_script: - coverage report - coverage json - coverage xml - coverage html coverage: '/^TOTAL .* (\d{1,3}\.\d{2})%$/' artifacts: paths: [results] reports: junit: results/xunit.xml coverage_report: coverage_format: cobertura path: results/coverage.xml Check Tag: stage: test extends: [.python] needs: ["Build Package"] rules: - if: $CI_COMMIT_TAG script: - pip install packaging pkginfo - | python <<-END from glob import glob from packaging.version import Version from pkginfo import Wheel wheel_path = glob("dist/*.whl")[0] wheel = Wheel(wheel_path) assert Version("$CI_COMMIT_TAG") == Version(wheel.version) END Upload Package: stage: deploy extends: [.python] needs: ["Build Package"] rules: - if: $CI_COMMIT_TAG script: - pip install twine - TWINE_USERNAME=gitlab-ci-token TWINE_PASSWORD=$CI_JOB_TOKEN twine upload --verbose --non-interactive --repository-url $CI_API_V4_URL/projects/$CI_PROJECT_ID/packages/pypi dist/* Documentation: stage: build extends: [.python] script: - pip install .[docs] - make -C doc html HTML_BUILDER=dirhtml BUILDDIR=../build artifacts: paths: [build] pages: stage: deploy needs: [Documentation] rules: - if: $CI_COMMIT_TAG script: - mv build/html public artifacts: paths: [public]
pyproject.toml +3 −0 Original line number Diff line number Diff line Loading @@ -83,6 +83,9 @@ disallow_any_explicit = true # disallow_any_expr = true [tool.pytest.ini_options] python_classes = "" [tool.coverage.run] data_file = "results/coverage.db" branch = true Loading