| name: CI | |
| on: | |
| push: | |
| branches: | |
| - trunk | |
| pull_request: | |
| branches: | |
| - trunk | |
| schedule: | |
| - cron: '0 1 * * *' | |
| permissions: | |
| contents: read # for actions/checkout to fetch code | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} | |
| cancel-in-progress: true | |
| env: | |
| # Needed if we want colors in pytest output without tty and script -e -c wrapper | |
| PY_COLORS: "1" | |
| FORCE_COLOR: "1" | |
| jobs: | |
| unit_tests: | |
| name: Unit Tests (Python ${{ matrix.python_version }}) | |
| runs-on: ${{ matrix.os }} | |
| timeout-minutes: 8 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| python_version: | |
| - "3.10" | |
| - "3.11" | |
| - "3.12" | |
| - "3.13" | |
| - "3.14" | |
| # cryptography is not compatible with older PyPy versions | |
| - "pypy-3.10" | |
| os: | |
| - ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Use Python ${{ matrix.python_version }} | |
| uses: actions/setup-python@v7 | |
| with: | |
| python-version: ${{ matrix.python_version }} | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d | |
| - name: Install OS / deb dependencies | |
| run: | | |
| sudo DEBIAN_FRONTEND=noninteractive apt-get update | |
| sudo DEBIAN_FRONTEND=noninteractive apt-get install -yq gcc libvirt-dev pkg-config | |
| - name: Cache uv | |
| uses: actions/cache@v6 | |
| with: | |
| path: ~/.cache/uv | |
| key: ${{ runner.os }}-uv-${{ hashFiles('uv.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-uv- | |
| - name: Install Python Dependencies | |
| run: uv sync --group ci --no-dev | |
| - name: Add .venv to PATH | |
| run: echo "${GITHUB_WORKSPACE}/.venv/bin" >> "$GITHUB_PATH" | |
| - name: Run unit tests tox target | |
| run: tox -e py${{ matrix.python_version }} | |
| - name: Run dist install checks tox target | |
| if: ${{ matrix.python_version != 'pypy-3.10' }} | |
| run: tox -e py${{ matrix.python_version }}-dist,py${{ matrix.python_version }}-dist-wheel | |
| code_coverage: | |
| name: Generate Code Coverage | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| python_version: [ "3.12" ] | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Use Python ${{ matrix.python_version }} | |
| uses: actions/setup-python@v7 | |
| with: | |
| python-version: ${{ matrix.python_version }} | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d | |
| - name: Install OS / deb dependencies | |
| run: | | |
| sudo DEBIAN_FRONTEND=noninteractive apt-get update | |
| sudo DEBIAN_FRONTEND=noninteractive apt-get install -yq graphviz gcc libvirt-dev pkg-config | |
| - name: Cache uv | |
| uses: actions/cache@v6 | |
| with: | |
| path: ~/.cache/uv | |
| key: ${{ runner.os }}-uv-${{ hashFiles('uv.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-uv- | |
| - name: Install Python Dependencies | |
| run: uv sync --group ci --no-dev | |
| - name: Add .venv to PATH | |
| run: echo "${GITHUB_WORKSPACE}/.venv/bin" >> "$GITHUB_PATH" | |
| - name: Run Checks | |
| run: tox -e coverage-ci | |
| - name: Upload Coverage to codecov.io | |
| uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 | |
| with: | |
| # We utilize secret for more realiable builds. Without secret being set, upload step | |
| # fails fairly often. | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| fail_ci_if_error: true | |
| verbose: true | |
| lint_checks: | |
| name: Run Various Lint and Other Checks | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| python_version: [ "3.12" ] | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Use Python ${{ matrix.python_version }} | |
| uses: actions/setup-python@v7 | |
| with: | |
| python-version: ${{ matrix.python_version }} | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d | |
| - name: Install OS / deb dependencies | |
| run: | | |
| sudo DEBIAN_FRONTEND=noninteractive apt-get update | |
| sudo DEBIAN_FRONTEND=noninteractive apt-get install -yq graphviz gcc libvirt-dev pkg-config | |
| - name: Cache uv | |
| uses: actions/cache@v6 | |
| with: | |
| path: ~/.cache/uv | |
| key: ${{ runner.os }}-uv-${{ hashFiles('uv.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-uv- | |
| - name: Install Python Dependencies | |
| run: uv sync --group ci --no-dev | |
| - name: Add .venv to PATH | |
| run: echo "${GITHUB_WORKSPACE}/.venv/bin" >> "$GITHUB_PATH" | |
| - name: Run shellcheck | |
| run: shellcheck dist/*.sh contrib/*.sh | |
| - name: Run Python Checks | |
| run: tox -e black-check,isort-check,pyupgrade,checks,import-timings,lint,pylint,mypy | |
| build_test_release_artifact: | |
| name: Build and Test Release Artifact | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| python_version: [ "3.12" ] | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Install system dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y libvirt-dev pkg-config gcc | |
| - name: Use Python ${{ matrix.python_version }} | |
| uses: actions/setup-python@v7 | |
| with: | |
| python-version: ${{ matrix.python_version }} | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d | |
| - name: Install OS / deb dependencies | |
| run: | | |
| sudo DEBIAN_FRONTEND=noninteractive apt-get update | |
| sudo DEBIAN_FRONTEND=noninteractive apt-get install -yq gcc libvirt-dev pkg-config | |
| - name: Cache uv | |
| uses: actions/cache@v6 | |
| with: | |
| path: ~/.cache/uv | |
| key: ${{ runner.os }}-uv-${{ hashFiles('uv.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-uv- | |
| - name: Install Python Dependencies | |
| run: | | |
| uv sync --group ci --group build --no-dev | |
| echo "${GITHUB_WORKSPACE}/.venv/bin" >> "$GITHUB_PATH" | |
| - name: Build Release Artifact | |
| run: | | |
| pip list installed | |
| python -m build -vv | |
| - name: Set Environment | |
| run: | | |
| export PYTHONPATH=. | |
| export VERSION=$(python -c "import libcloud ; print(libcloud.__version__)") | |
| echo "VERSION=${VERSION}" >> "$GITHUB_ENV" | |
| - name: Verify Tarball Release Artifact | |
| run: | | |
| # Verify tarball file exists | |
| export TARBALL_FILENAME="apache_libcloud-${VERSION}.tar.gz" | |
| ls -la "dist/${TARBALL_FILENAME}" | |
| cd dist/ | |
| # Unpack tarball and verify + run the tests | |
| tar -xzvf "${TARBALL_FILENAME}" | |
| cd "apache_libcloud-${VERSION}/" | |
| tox -c tox.ini -epy3.12 | |
| - name: Verify Wheel Release Artifact | |
| run: | | |
| # Verify wheel file exists | |
| export WHEEL_FILENAME="apache_libcloud-${VERSION}-py3-none-any.whl" | |
| ls -la "dist/${WHEEL_FILENAME}" | |
| cd dist/ | |
| # Unpack wheel and verify + run tests | |
| unzip "${WHEEL_FILENAME}" -d "wheel" | |
| cd wheel | |
| # Since wheel doesn't include those files, we need to manually copy them over from | |
| # repo root so we can run the tests | |
| cp ../../tox.ini . | |
| cp ../../pyproject.toml . | |
| cp ../../libcloud/test/secrets.py-dist libcloud/test/secrets.py-dist | |
| tox -c tox.ini -epy3.12 | |
| build_test_docker_image: | |
| name: Build and Verify Docker Image | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| python_version: [ "3.12" ] | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Build Testing Docker Image | |
| run: docker build -f contrib/Dockerfile -t libcloud_runtest_img . | |
| - name: Verify Image Works | |
| # This step runs checks under various Python versions and it's slow so | |
| # we only run it on nightly basis | |
| if: ${{ github.event.schedule == '0 1 * * *' }} | |
| run: | | |
| docker run libcloud_runtest_img | |
| security_checks: | |
| name: Run Security Checks | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| python_version: [ "3.12" ] | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Use Python ${{ matrix.python_version }} | |
| uses: actions/setup-python@v7 | |
| with: | |
| python-version: ${{ matrix.python_version }} | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d | |
| - name: Install OS / deb dependencies | |
| run: | | |
| sudo DEBIAN_FRONTEND=noninteractive apt-get update | |
| sudo DEBIAN_FRONTEND=noninteractive apt-get install -yq gcc libvirt-dev pkg-config | |
| - name: Cache uv | |
| uses: actions/cache@v6 | |
| with: | |
| path: ~/.cache/uv | |
| key: ${{ runner.os }}-uv-${{ hashFiles('uv.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-uv- | |
| - name: Install Python Dependencies | |
| run: uv sync --group dev --group docs | |
| - name: Add .venv to PATH | |
| run: echo "${GITHUB_WORKSPACE}/.venv/bin" >> "$GITHUB_PATH" | |
| - name: Ensure pip is available | |
| run: | | |
| python -m ensurepip --upgrade | |
| python -m pip install --upgrade pip | |
| - name: Install Library Into Virtualenv | |
| run: | | |
| python -m venv venv/ | |
| source venv/bin/activate | |
| python -m pip install --upgrade pip | |
| python -m pip install . | |
| - name: Run Pip Audit Check On Main Library Dependencies | |
| uses: pypa/gh-action-pip-audit@1220774d901786e6f652ae159f7b6bc8fea6d266 # v1.1.0 | |
| with: | |
| virtual-environment: venv/ | |
| # setuptools which we don't install or depend on directly | |
| # PYSEC-2023-228 - pip vulnerability and we don't install pip directly | |
| ignore-vulns: | | |
| GHSA-r9hx-vwmv-q579 | |
| PYSEC-2022-43012 | |
| PYSEC-2023-228 | |
| - name: Cleanup | |
| run: rm -rf venv/ || true | |
| - name: Run Pip Audit Check On All Development And Test Dependencies | |
| uses: pypa/gh-action-pip-audit@1220774d901786e6f652ae159f7b6bc8fea6d266 # v1.1.0 | |
| with: | |
| virtual-environment: .venv | |
| # setuptools which we don't install or depend on directly | |
| ignore-vulns: | | |
| GHSA-r9hx-vwmv-q579 | |
| - name: Run Bandit Check | |
| run: tox -e bandit | |
| micro-benchmarks: | |
| name: Micro Benchmarks | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| python_version: [ "3.12" ] | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Use Python ${{ matrix.python_version }} | |
| uses: actions/setup-python@v7 | |
| with: | |
| python-version: ${{ matrix.python_version }} | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d | |
| - name: Install OS / deb dependencies | |
| run: | | |
| sudo DEBIAN_FRONTEND=noninteractive apt-get update | |
| sudo DEBIAN_FRONTEND=noninteractive apt-get install -yq graphviz gcc libvirt-dev pkg-config | |
| - name: Cache uv | |
| uses: actions/cache@v6 | |
| with: | |
| path: ~/.cache/uv | |
| key: ${{ runner.os }}-uv-${{ hashFiles('uv.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-uv- | |
| - name: Install Python Dependencies | |
| run: uv sync --group ci --no-dev | |
| - name: Add .venv to PATH | |
| run: echo "${GITHUB_WORKSPACE}/.venv/bin" >> "$GITHUB_PATH" | |
| - name: Run Micro Benchmarks | |
| run: tox -e micro-benchmarks | |
| docs: | |
| name: Build and upload Documentation | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| python_version: [ "3.12" ] | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Use Python ${{ matrix.python_version }} | |
| uses: actions/setup-python@v7 | |
| with: | |
| python-version: ${{ matrix.python_version }} | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d | |
| - name: Print Environment Info | |
| run: printenv | sort | |
| - name: Install OS / deb dependencies | |
| run: | | |
| sudo DEBIAN_FRONTEND=noninteractive apt-get update | |
| sudo DEBIAN_FRONTEND=noninteractive apt-get install -yq graphviz gcc libvirt-dev pkg-config | |
| - name: Cache uv | |
| uses: actions/cache@v6 | |
| with: | |
| path: ~/.cache/uv | |
| key: ${{ runner.os }}-uv-${{ hashFiles('uv.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-uv- | |
| - name: Install Python Dependencies | |
| run: uv sync --group ci --no-dev | |
| - name: Add .venv to PATH | |
| run: echo "${GITHUB_WORKSPACE}/.venv/bin" >> "$GITHUB_PATH" | |
| - name: Build Docs | |
| run: tox -e docs | |
| - name: Trigger ReadTheDocs build | |
| if: ${{ github.ref_name == 'trunk' }} | |
| env: | |
| RTD_TOKEN: ${{ secrets.RTD_TOKEN }} | |
| BRANCH_NAME: "trunk" | |
| run: | | |
| uv pip install requests | |
| python ./contrib/trigger_rtd_build.py |