diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml new file mode 100644 index 00000000..5484c629 --- /dev/null +++ b/.github/workflows/publish.yaml @@ -0,0 +1,27 @@ +name: Publish to PyPI +on: + workflow_dispatch: + release: + types: + - published +# push: +# tags: +# - "[0-9]+.[0-9]+*" + +jobs: + publish: + name: Build and publish + if: startsWith(github.event.ref, 'refs/tags') + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: 3.9 + - run: pip install --upgrade setuptools wheel twine + - run: python setup.py sdist bdist_wheel + - uses: pypa/gh-action-pypi-publish@master + with: + user: __token__ + password: ${{ secrets.pypi_token }} + skip_existing: true diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml new file mode 100644 index 00000000..11511cd3 --- /dev/null +++ b/.github/workflows/tests.yaml @@ -0,0 +1,155 @@ +name: Tests +on: + workflow_dispatch: + push: + branches: + - master + - release/** + paths-ignore: + - "*.md" + - "docs/**" + pull_request: + branches: + - master + schedule: + - cron: "13 3 * * *" + +jobs: + linters: + name: Linting and static analysis + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: "3.9" + - run: pip install -r requirements.txt + - run: isort . --check --diff + continue-on-error: true + - run: isort examples --settings=examples --check --diff + continue-on-error: true + + unit-tests: + strategy: + fail-fast: false + matrix: + python-version: [ "3.7", "3.8", "3.9" ] + name: Python ${{ matrix.python-version }} + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - run: pip install -r requirements.txt + - run: mypy kopf --strict --pretty + - run: pytest --cov=kopf --cov-branch --junit-xml=junit.xml + - run: coveralls || true + if: ${{ success() }} + - run: codecov --flags unit + if: ${{ success() }} +# - uses: actions/upload-artifact@v2 +# with: +# name: JUnit for ${{ matrix.python-version }} +# path: junit.xml +# if: ${{ always() }} + + functional: + strategy: + fail-fast: false + matrix: + k3s: [latest, v1.18.8+k3s1, v1.16.14+k3s1] + client: [true, false] + crdapi: ["", v1beta1] + exclude: + - client: true + - crdapi: v1beta1 + include: + - k3s: v1.16.14+k3s1 + crdapi: v1beta1 + client: false + - k3s: latest + crdapi: "" + client: true + name: >- + K3s ${{matrix.k3s}} + ${{matrix.crdapi && format('CRD={0}', matrix.crdapi) || ''}} + ${{matrix.client && '+client' || ''}} + runs-on: ubuntu-20.04 + env: + K3S: ${{ matrix.k3s }} + CLIENT: ${{ matrix.client || '' }} + CRDAPI: ${{ matrix.crdapi || '' }} + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: "3.9" + - run: pip install -r requirements.txt + - run: tools/install-clients.sh + - run: tools/install-kubectl.sh + - run: tools/install-k3d-k3s.sh + - run: pytest --only-e2e + + full-scale-crd-v1: +# if: ${{ github.event_name == 'schedule' }} # TODO + strategy: + fail-fast: false + matrix: + k8s: [latest, v1.19.0, v1.18.8, v1.17.11, v1.16.14] + client: [true, false] + crdapi: [""] + python-version: ["3.9"] + exclude: + - client: true + include: + - k8s: latest + client: true + name: >- + K8s ${{matrix.k8s}} + ${{matrix.crdapi && format('CRD={0}', matrix.crdapi) || ''}} + ${{matrix.client && '+client' || ''}} + runs-on: ubuntu-20.04 + env: + K8S: ${{ matrix.k8s }} + CLIENT: ${{ matrix.client || '' }} + CRDAPI: ${{ matrix.crdapi || '' }} + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - run: pip install -r requirements.txt + - run: tools/install-clients.sh + - run: tools/install-kubectl.sh + - run: tools/install-minikube.sh + - run: pytest --only-e2e + + full-scale-crd-v1beta1: +# if: ${{ github.event_name == 'schedule' }} # TODO + strategy: + fail-fast: false + matrix: + k8s: [v1.16.14, v1.15.12, v1.14.10, v1.13.12] + client: [false] + crdapi: [v1beta1] + python-version: ["3.9"] + name: >- + K8s ${{matrix.k8s}} + ${{matrix.crdapi && format('CRD={0}', matrix.crdapi) || ''}} + ${{matrix.client && '+client' || ''}} + runs-on: ubuntu-20.04 + env: + K8S: ${{ matrix.k8s }} + CLIENT: ${{ matrix.client || '' }} + CRDAPI: ${{ matrix.crdapi || '' }} + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - run: pip install -r requirements.txt + - run: tools/install-clients.sh + - run: tools/install-kubectl.sh + - run: tools/install-minikube.sh + - run: pytest --only-e2e diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 608590e6..00000000 --- a/.travis.yml +++ /dev/null @@ -1,111 +0,0 @@ -# The primary environment for testing. Some jobs selectively override these settings. -os: linux -arch: amd64 -dist: focal -language: python -python: "3.9" - -# Only test the final merges and releases. The work-in-progress branches are tested by PR builds. -branches: - only: - - master - - /^release\/.*$/ - - /^\d+\.\d+(\.\d+)?(\.?(rc|dev|pre|post)\d+)?(-\S*)?(\+\S*)?$/ - -# Linting is super-fast and lightweight, gives the near-instant feedback if code is wrong. -# It does not depend on the environment (services, dependencies, even the framework itself). -# Currently, most linters are optional and performed manually from time to time. This will change. -_linting: &linting -# install: [] # no requirements.txt # TODO: Uncomment again when pre-commit is used (saves ~15s) - services: [] # no docker & co - before_script: [] - script: - - isort . --check --diff || true - - isort examples --settings=examples --check --diff || true - -# Unit-tests depend on a lightweight environment of the framework and its dependencies only, no K8s. -# Type-checking also needs the dependencies installed, but it goes first for faster failure. -_unittests: &unittests - services: [] # no docker & co - before_script: [] - script: - - mypy kopf --strict --pretty - - pytest --cov=kopf --cov-branch - after_success: - - coveralls || true - - codecov --flags unit - -# Realistic tests are heavy, slow, but needed even for PRs. They use real K8s of different versions. -# Coverage is not measured in these tests, as all lines will be covered anyway, even if some -# potentially buggy scenarios/edge-cases are missing -- such coverage is not trustworthy. -_integration: &realistic - services: - - docker - before_script: - - tools/install-clients.sh - - tools/install-kubectl.sh - - tools/install-k3d-k3s.sh - script: - - pytest --only-e2e - -# Full-scale tests run all setups and all K8s versions (including those not supported by lightweight -# K3d/K3s in PR/branch-tests). They are too slow and too numerous for PRs, so they run by cron only. -# To run/debug in a PR, comment out the `if:` line. Uncomment it back before merging. -_nightly: &fullscale - if: type == cron - services: - - docker - before_script: - - tools/install-clients.sh - - tools/install-kubectl.sh - - tools/install-minikube.sh - script: - - pytest --only-e2e - -# The job matrix combines all scripts with all intended setups. -# Only one Python version is tested with all supported K8s versions: to check for API compatibility. -# Other Python versions are tested with only one K8s version: if it works for one, it works for all. -# Ordering is important: 4 heavy jobs (5m) start asap, 3 fast jobs (1+2+2 min) run sequentially, -# thus fitting into Travis's 5-job limit with the fastest possible outcome. For cron, ignore timing. -jobs: - include: - - # Regular (daily/nightly) tests for all and old K8s versions. Very slow (8m). - - { <<: *fullscale, env: K8S=latest CLIENT=yes } - - { <<: *fullscale, env: K8S=latest } - - { <<: *fullscale, env: K8S=v1.19.0 } - - { <<: *fullscale, env: K8S=v1.18.8 } - - { <<: *fullscale, env: K8S=v1.17.11 } - - { <<: *fullscale, env: K8S=v1.16.14 } - - { <<: *fullscale, env: K8S=v1.16.14 CRDAPI=v1beta1 } - - { <<: *fullscale, env: K8S=v1.15.12 CRDAPI=v1beta1 } - - { <<: *fullscale, env: K8S=v1.14.10 CRDAPI=v1beta1 } - - { <<: *fullscale, env: K8S=v1.13.12 CRDAPI=v1beta1 } - - # Integration tests are slow (5-6m). Limit to 4 representative setups for faster PR feedbacks. - - { <<: *realistic, env: K3S=latest CLIENT=yes } - - { <<: *realistic, env: K3S=v1.18.8+k3s1 } - - { <<: *realistic, env: K3S=v1.16.14+k3s1 } - - { <<: *realistic, env: K3S=v1.16.14+k3s1 CRDAPI=v1beta1 } - - # Linting is super-fast and lightweight (40s), gives the near-instant feedback. - # Unit-tests are relatively fast (2m), but no integration tests, no k8s installed. - # This pack of jobs takes roughly 5m, which is a duration of one realistic job. - - { <<: *linting, name: Linting and static analysis } - - { <<: *unittests, python: "3.7" } - - { <<: *unittests, python: "3.8" } - - { <<: *unittests, python: "3.9" } - - fast_finish: true - allow_failures: - - python: "3.10-dev" - -deploy: - provider: pypi - username: "__token__" - password: - secure: "jkf7ncg2doyqEkASa4NFtNt9BfOcFvGvFIAj/jU55sCkKGfvavzC262/kmJnTZpF1ZStjL+z3AwSLT09cYtlujA/FRdPmuNzyRgr2j4D20Txx5whHj8zYdklquhEHbXo7FU+nQTDxkLqr35KEnMBIzoesz7xHoOH/MLzK5w2Ow8DprAjVVSY0Dv+glJ15qWo/pwNp1xetMGYjdO4ys4amdsvRlU4LmCcuMf5LsnuJyuR7yHsBs6CqmnitJezZ+fgGKqJDEC+jy/+q7aOc6V2iCDsOH5NNniUeVKTuDhmvK+1y146VVqWw+RqIG27cMyYbocmJhYRBQoLbwCKLPKF2l2YtgjKdt9izyYbjjBAVIUtsavGrsNSk08ujS8OCs9/4YXFFMjTTKwF+Hy0RqmIMNK2ymn8pWpo9HTJT2td9b0HkVikDX3D8sezD1koSxDTWYFs3MMVDPTA9lWL3sIFVHhQRr3rlk+qsoSsP5/SvVMGJv4NIjIi+SZaLvqR+aPaO1H92zVkhcMbNN3cNHE8ak1LXUmnr008xjJzsT+Y+wthx6G1zpFRSLH4dP7myxF0Zk7uJQPhaQTflICseVW4mp72HeraTKc+QHKZthTXwFeMVVSTdgNpVMpfYnjolkGXdubDbhhDhz6B4OzIRZXqiIUANHsT5zGiS0OjN7Pa4lY=" - distributions: sdist bdist_wheel - skip_existing: true - on: - tags: true # prohibit local versions not on the releases diff --git a/README.md b/README.md index 23ddb921..f7a88fb2 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Kubernetes Operator Pythonic Framework (Kopf) -[![Build Status](https://travis-ci.org/nolar/kopf.svg?branch=master)](https://travis-ci.org/nolar/kopf) +[![Tests](https://github.com/nolar/kopf/workflows/Tests/badge.svg)](https://github.com/nolar/kopf/actions) [![codecov](https://codecov.io/gh/nolar/kopf/branch/master/graph/badge.svg)](https://codecov.io/gh/nolar/kopf) [![Coverage Status](https://coveralls.io/repos/github/nolar/kopf/badge.svg?branch=master)](https://coveralls.io/github/nolar/kopf?branch=master) [![Total alerts](https://img.shields.io/lgtm/alerts/g/nolar/kopf.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/nolar/kopf/alerts/) diff --git a/docs/contributing.rst b/docs/contributing.rst index ddac8557..c82e95b7 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -105,23 +105,3 @@ Code reviews You can use one of the existing or closed issues that match your topic best. * The PRs can be reviewed and commented by anyone, but can be approved only by the project maintainers. - - -Private CI/CD -============= - -The existing setup runs the Travis CI builds on every push -to the existing pull requests of the upstream repository. - -In case you do not want to create a pull request yet, -but want to run the builds for your branch, -enable Travis CI for your own fork: - -* Create a `Travis CI `_ account. -* Find your fork in the list of repos. -* Click the toggle. -* Push a feature branch to ``origin`` (see above). -* Observe how Travis runs the tests in Travis CI in your account. - -When ready, create a PR to the upstream repository. -This will run the tests in the upstream's Travis account. diff --git a/examples/09-testing/test_example_09.py b/examples/09-testing/test_example_09.py index 42d08bb3..1ccf1d18 100644 --- a/examples/09-testing/test_example_09.py +++ b/examples/09-testing/test_example_09.py @@ -11,7 +11,7 @@ @pytest.fixture(scope='session') def crd_yaml(): - crd_api = os.environ.get('CRDAPI', 'v1') + crd_api = os.environ.get('CRDAPI') or 'v1' crd_file = 'crd.yaml' if crd_api == 'v1' else f'crd-{crd_api}.yaml' return os.path.relpath(os.path.join(os.path.dirname(__file__), '..', crd_file)) diff --git a/examples/11-filtering-handlers/test_example_11.py b/examples/11-filtering-handlers/test_example_11.py index 38e24cbb..dd7377f0 100644 --- a/examples/11-filtering-handlers/test_example_11.py +++ b/examples/11-filtering-handlers/test_example_11.py @@ -11,7 +11,7 @@ @pytest.fixture(scope='session') def crd_yaml(): - crd_api = os.environ.get('CRDAPI', 'v1') + crd_api = os.environ.get('CRDAPI') or 'v1' crd_file = 'crd.yaml' if crd_api == 'v1' else f'crd-{crd_api}.yaml' return os.path.relpath(os.path.join(os.path.dirname(__file__), '..', crd_file)) diff --git a/tests/e2e/conftest.py b/tests/e2e/conftest.py index c7d11807..5e6efc20 100644 --- a/tests/e2e/conftest.py +++ b/tests/e2e/conftest.py @@ -18,14 +18,14 @@ def exampledir(request): @pytest.fixture(scope='session') def peering_yaml(): - crd_api = os.environ.get('CRDAPI', 'v1') + crd_api = os.environ.get('CRDAPI') or 'v1' crd_file = 'peering.yaml' if crd_api == 'v1' else f'peering-{crd_api}.yaml' return f'{crd_file}' @pytest.fixture(scope='session') def crd_yaml(): - crd_api = os.environ.get('CRDAPI', 'v1') + crd_api = os.environ.get('CRDAPI') or 'v1' crd_file = 'crd.yaml' if crd_api == 'v1' else f'crd-{crd_api}.yaml' return f'examples/{crd_file}' diff --git a/tools/install-kind.sh b/tools/install-kind.sh index 83c5d510..be9e85d6 100755 --- a/tools/install-kind.sh +++ b/tools/install-kind.sh @@ -19,7 +19,7 @@ if [[ "$K8S" == latest ]] ; then K8S="$( curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt )" fi -curl -Lo ./kind https://kind.sigs.k8s.io/dl/"$KIND"/kind-linux-"$TRAVIS_CPU_ARCH" +curl -Lo ./kind https://kind.sigs.k8s.io/dl/"$KIND"/kind-linux-amd64 chmod +x ./kind sudo mv ./kind /usr/local/bin/ diff --git a/tools/install-kubectl.sh b/tools/install-kubectl.sh index 8f045f7c..d7ffdf0c 100755 --- a/tools/install-kubectl.sh +++ b/tools/install-kubectl.sh @@ -13,6 +13,6 @@ if [[ "$K8S" == latest ]] ; then K8S="$( curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt )" fi -curl -Lo kubectl https://storage.googleapis.com/kubernetes-release/release/"$K8S"/bin/linux/"$TRAVIS_CPU_ARCH"/kubectl +curl -Lo kubectl https://storage.googleapis.com/kubernetes-release/release/"$K8S"/bin/linux/amd64/kubectl chmod +x kubectl sudo mv kubectl /usr/local/bin/