Skip to content

CI

CI #546

Workflow file for this run

name: CI
on:
release:
types: [published]
pull_request:
push:
branches: [main]
tags:
- "v*"
defaults:
run:
shell: bash
jobs:
probe_tests:
name: Unit tests / ${{ matrix.python }} / ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
python: ["3.11", "3.12"]
fail-fast: true
env:
OS: ${{ matrix.os }}
PYTHON: ${{ matrix.python }}
steps:
- uses: actions/checkout@v4
- name: Install uv
id: setup-uv
uses: astral-sh/setup-uv@v2
with:
enable-cache: 'true'
- name: Install Python ${{ matrix.python }}
id: setup-python
run: uv python install ${{ matrix.python }}
- name: Sync Dependencies
run: uv sync --frozen --no-dev
- name: Run Tests
run: |
uv run pytest tests --cov netcheck --cov-report=lcov --cov-report=term
timeout-minutes: 10
- name: Coveralls Parallel
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.github_token }}
flag-name: Unittests-${{ matrix.os }}-${{ matrix.python-version }}
parallel: true
path-to-lcov: ./coverage.lcov
probe_coverage:
name: Probe Code Coverage
needs: probe_tests
runs-on: ubuntu-latest
steps:
- name: Coveralls Finished
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.github_token }}
parallel-finished: true
probe_package:
name: Probe Library Packaging
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install uv
id: setup-uv
uses: astral-sh/setup-uv@v2
with:
enable-cache: true
- name: Install Python
run: uv python install 3.12
- name: Sync dependencies
run: uv sync --frozen --no-dev
- name: Artifact creation
run: uv build
- name: Save artifacts
uses: actions/upload-artifact@v4
with:
name: dist
path: ./dist
upload_pypi:
name: Release to PyPi
needs: [probe_package]
runs-on: ubuntu-latest
# upload to PyPI only on release
if: github.event.release && github.event.action == 'published'
steps:
- uses: actions/download-artifact@v4.1.7
with:
name: dist
path: dist
- uses: pypa/gh-action-pypi-publish@v1.8.11
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
probe_docker:
name: Build Probe Image
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
id-token: write # needed for signing the images with GitHub OIDC Token
env:
IMAGE_NAME: netchecks
IMAGE_REGISTRY: ghcr.io
IMAGE_REPOSITORY: hardbyte
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: ${{env.IMAGE_REGISTRY}}/${{env.IMAGE_REPOSITORY}}/${{env.IMAGE_NAME}}
tags: |
type=sha
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.IMAGE_REGISTRY }}
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and push
id: docker_build
uses: docker/build-push-action@v6
with:
context: .
push: true
platforms: linux/amd64,linux/arm64
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha,scope=probe
cache-to: type=gha,mode=max,scope=probe
# ---------------------------------------------------------------------------
# Operator Docker — build each platform natively, then merge manifests.
# This avoids QEMU emulation for Rust (which is extremely slow).
# ---------------------------------------------------------------------------
operator_docker:
name: Build Operator Image (${{ matrix.platform }})
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
- platform: linux/amd64
runner: ubuntu-latest
- platform: linux/arm64
runner: ubuntu-24.04-arm
permissions:
contents: read
packages: write
id-token: write
env:
IMAGE_NAME: netchecks-operator
IMAGE_REGISTRY: ghcr.io
IMAGE_REPOSITORY: hardbyte
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: ${{env.IMAGE_REGISTRY}}/${{env.IMAGE_REPOSITORY}}/${{env.IMAGE_NAME}}
tags: |
type=sha
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.IMAGE_REGISTRY }}
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and push by digest
id: build
uses: docker/build-push-action@v6
with:
context: operator
platforms: ${{ matrix.platform }}
outputs: type=image,"name=${{env.IMAGE_REGISTRY}}/${{env.IMAGE_REPOSITORY}}/${{env.IMAGE_NAME}}",push-by-digest=true,name-canonical=true,push=true
cache-from: type=gha,scope=operator-${{ matrix.platform }}
cache-to: type=gha,mode=max,scope=operator-${{ matrix.platform }}
- name: Export digest
run: |
mkdir -p ${{ runner.temp }}/digests
digest="${{ steps.build.outputs.digest }}"
touch "${{ runner.temp }}/digests/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v4
with:
name: operator-digests-${{ matrix.platform == 'linux/amd64' && 'amd64' || 'arm64' }}
path: ${{ runner.temp }}/digests/*
if-no-files-found: error
retention-days: 1
operator_docker_merge:
name: Merge Operator Manifests
needs: operator_docker
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
id-token: write
env:
IMAGE_NAME: netchecks-operator
IMAGE_REGISTRY: ghcr.io
IMAGE_REPOSITORY: hardbyte
steps:
- name: Download digests
uses: actions/download-artifact@v4
with:
path: ${{ runner.temp }}/digests
pattern: operator-digests-*
merge-multiple: true
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: ${{env.IMAGE_REGISTRY}}/${{env.IMAGE_REPOSITORY}}/${{env.IMAGE_NAME}}
tags: |
type=sha
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.IMAGE_REGISTRY }}
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Create manifest list and push
working-directory: ${{ runner.temp }}/digests
run: |
docker buildx imagetools create \
$(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
$(printf '${{env.IMAGE_REGISTRY}}/${{env.IMAGE_REPOSITORY}}/${{env.IMAGE_NAME}}@sha256:%s ' *)
- name: Inspect image
run: |
docker buildx imagetools inspect \
${{env.IMAGE_REGISTRY}}/${{env.IMAGE_REPOSITORY}}/${{env.IMAGE_NAME}}:${{ steps.meta.outputs.version }}
operator_tests:
name: Operator Unit Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Cache cargo
uses: Swatinem/rust-cache@v2
with:
workspaces: operator -> target
- name: Check formatting
run: cargo fmt --all -- --check
working-directory: operator
- name: Clippy
run: cargo clippy --all-targets --all-features -- -D warnings
working-directory: operator
- name: Run tests
run: cargo test
working-directory: operator
k8s:
name: Kubernetes Integration Tests
needs: [probe_docker, operator_docker_merge]
runs-on: ubuntu-latest
timeout-minutes: 20
env:
KIND_VERSION: v0.18.0
KIND_CONFIG: .github/kind-config.yaml
TIMEOUT: 2m
LOG_TIME: 30m
cilium_version: 1.14.3
cilium_cli_version: v0.15.11
kubectl_version: v1.26.3
PROBE_IMAGE_NAME: netchecks
OPERATOR_IMAGE_NAME: netchecks-operator
IMAGE_REGISTRY: ghcr.io
IMAGE_REPOSITORY: hardbyte
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Python
id: setup-python
uses: actions/setup-python@v4
with:
python-version: "3.12"
- name: Install Python test dependencies
run: pip install pytest
- name: Install kubectl
run: |
curl -sLO "https://dl.k8s.io/release/${{ env.kubectl_version }}/bin/linux/amd64/kubectl"
curl -sLO "https://dl.k8s.io/${{ env.kubectl_version }}/bin/linux/amd64/kubectl.sha256"
echo "$(cat kubectl.sha256) kubectl" | sha256sum --check
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
kubectl version --client
- name: Install cilium CLI binary
run: |
curl -L --fail --remote-name-all https://github.com/cilium/cilium-cli/releases/download/${{ env.cilium_cli_version }}/cilium-linux-amd64.tar.gz{,.sha256sum}
sha256sum --check cilium-linux-amd64.tar.gz.sha256sum
sudo tar xzvfC cilium-linux-amd64.tar.gz /usr/local/bin
cilium version --client
- name: Fetch kind cilium config
run: |
curl -LO https://raw.githubusercontent.com/cilium/cilium/1.14.3/Documentation/installation/kind-config.yaml
- name: Create kind cluster
uses: helm/kind-action@v1
with:
version: ${{ env.KIND_VERSION }}
cluster_name: kind
config: kind-config.yaml
- name: Install Cilium
run: |
cilium install --version ${{ env.cilium_version }}
- name: Wait for Cilium Operator
run: |
cilium status --wait
- name: Get Cluster Info
run: |
kubectl cluster-info
export KUBE_API=$(kubectl config view -o jsonpath='{.clusters[0].cluster.server}')
kind get nodes
- name: Load Netchecks Images into Kind
run: |
docker pull ${{env.IMAGE_REGISTRY}}/${{env.IMAGE_REPOSITORY}}/${{env.PROBE_IMAGE_NAME}}:sha-${GITHUB_SHA::7}
docker pull ${{env.IMAGE_REGISTRY}}/${{env.IMAGE_REPOSITORY}}/${{env.OPERATOR_IMAGE_NAME}}:sha-${GITHUB_SHA::7}
kind load docker-image ${{env.IMAGE_REGISTRY}}/${{env.IMAGE_REPOSITORY}}/${{env.PROBE_IMAGE_NAME}}:sha-${GITHUB_SHA::7}
kind load docker-image ${{env.IMAGE_REGISTRY}}/${{env.IMAGE_REPOSITORY}}/${{env.OPERATOR_IMAGE_NAME}}:sha-${GITHUB_SHA::7}
- name: Prepare Netchecks Operator Helm Chart
run: |
helm dependency build operator/charts/netchecks
- name: Install Netchecks Operator (helm chart)
run: |
helm upgrade --install netchecks-operator operator/charts/netchecks -n netchecks --create-namespace
- name: Uninstall Netchecks Operator
run: |
helm uninstall netchecks-operator -n netchecks
- name: Run Integration Tests (no Cilium)
run: |
cd operator
export NETCHECKS_IMAGE_TAG=sha-${GITHUB_SHA::7}
pytest -v -x
timeout-minutes: 10
- name: Run Integration Tests (with Cilium)
run: |
cd operator
export NETCHECKS_IMAGE_TAG=sha-${GITHUB_SHA::7}
export INCLUDE_CILIUM_TESTS=1
pytest -x
timeout-minutes: 10
- name: Cleanup
if: ${{ always() }}
run: |
cilium status
kubectl get pods --all-namespaces -o wide
shell: bash {0} # Disable default fail-fast behaviour so that all commands run independently