Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 34 additions & 25 deletions .github/actions/setup-kind-cluster/action.yaml
Original file line number Diff line number Diff line change
@@ -1,38 +1,42 @@
name: Setup Kind cluster with NeMo Platform
description: >
Creates a Kind cluster, installs tooling (kind, kubectl, Helm, uv),
pre-pulls images, deploys NeMo Platform via Helm, and waits for the
API to become healthy.
optionally deploys NeMo Platform via Helm, and waits for the API to become
healthy.

inputs:
kind_cluster_name:
kind-cluster-name:
description: Kind cluster name
required: true
kube_namespace:
install-nemo-platform:
description: Deploy NeMo Platform into the Kind cluster
required: false
default: "true"
kube-namespace:
description: Kubernetes namespace for NeMo Platform
required: false
default: nemo-platform
kube_gateway_name:
kube-gateway-name:
description: Gateway resource name
required: false
default: nmp-e2e-gateway
image_registry:
image-registry:
description: Container image registry
required: true
image_tag:
image-tag:
description: Container image tag
required: true
helm_values:
helm-values:
description: Helm values file path (relative to repo root)
required: false
default: e2e/k8s/values/kind.yaml
kind_image_pull_token:
kind-image-pull-token:
description: Token for pulling images into Kind
required: true
kind_image_pull_user:
kind-image-pull-user:
description: Username for pulling images into Kind
required: true
ngc_api_key:
ngc-api-key:
description: NGC API key (can be a placeholder for CPU-only)
required: false
default: not-used
Expand Down Expand Up @@ -108,22 +112,23 @@ runs:
- name: Start kind cluster
shell: bash
env:
KIND_CLUSTER_NAME: ${{ inputs.kind_cluster_name }}
KUBE_NAMESPACE: ${{ inputs.kube_namespace }}
NGC_API_KEY: ${{ inputs.ngc_api_key }}
KIND_CLUSTER_NAME: ${{ inputs['kind-cluster-name'] }}
KUBE_NAMESPACE: ${{ inputs['kube-namespace'] }}
NGC_API_KEY: ${{ inputs['ngc-api-key'] }}
GITHUB_TOKEN: ${{ inputs['kind-image-pull-token'] }}
run: bash e2e/k8s/scripts/setup_local_kind_cpu.sh

- name: Set default kubectl namespace
shell: bash
env:
NAMESPACE: ${{ inputs.kube_namespace }}
NAMESPACE: ${{ inputs['kube-namespace'] }}
run: kubectl config set-context --current --namespace="${NAMESPACE}"

- name: Verify Gateway API setup
shell: bash
env:
NAMESPACE: ${{ inputs.kube_namespace }}
KUBE_GATEWAY_NAME: ${{ inputs.kube_gateway_name }}
NAMESPACE: ${{ inputs['kube-namespace'] }}
KUBE_GATEWAY_NAME: ${{ inputs['kube-gateway-name'] }}
run: |
set -euo pipefail
kubectl wait --for=condition=Established crd/gateways.gateway.networking.k8s.io --timeout=2m
Expand All @@ -132,27 +137,30 @@ runs:
kubectl -n "${NAMESPACE}" get gateway "${KUBE_GATEWAY_NAME}"

- name: Pre-pull GHCR images into kind
if: ${{ inputs['install-nemo-platform'] == 'true' }}
shell: bash
env:
KIND_IMAGE_PULL_TOKEN: ${{ inputs.kind_image_pull_token }}
KIND_IMAGE_PULL_USER: ${{ inputs.kind_image_pull_user }}
NMP_E2E_REGISTRY: ${{ inputs.image_registry }}
NMP_E2E_TAG: ${{ inputs.image_tag }}
KIND_IMAGE_PULL_TOKEN: ${{ inputs['kind-image-pull-token'] }}
KIND_IMAGE_PULL_USER: ${{ inputs['kind-image-pull-user'] }}
NMP_E2E_REGISTRY: ${{ inputs['image-registry'] }}
NMP_E2E_TAG: ${{ inputs['image-tag'] }}
run: |
e2e/k8s/scripts/prepull_kind_images.sh \
"${NMP_E2E_REGISTRY}/nmp-api:${NMP_E2E_TAG}" \
"${NMP_E2E_REGISTRY}/nmp-cpu-tasks:${NMP_E2E_TAG}"

- name: Install NeMo Platform
if: ${{ inputs['install-nemo-platform'] == 'true' }}
shell: bash
env:
NAMESPACE: ${{ inputs.kube_namespace }}
NMP_E2E_REGISTRY: ${{ inputs.image_registry }}
NMP_E2E_TAG: ${{ inputs.image_tag }}
HELM_VALUES: ${{ inputs.helm_values }}
NAMESPACE: ${{ inputs['kube-namespace'] }}
NMP_E2E_REGISTRY: ${{ inputs['image-registry'] }}
NMP_E2E_TAG: ${{ inputs['image-tag'] }}
HELM_VALUES: ${{ inputs['helm-values'] }}
REQUIRE_NMP_E2E_IMAGES: "true"
POSTGRES_IMAGE: docker.io/library/postgres
BUSYBOX_IMAGE: docker.io/library/busybox
GITHUB_TOKEN: ${{ inputs['kind-image-pull-token'] }}
run: |
if ! e2e/k8s/scripts/install_helm_e2e.sh; then
echo "--- helm list -A ---"
Expand All @@ -165,6 +173,7 @@ runs:
fi

- name: Wait for API
if: ${{ inputs['install-nemo-platform'] == 'true' }}
shell: bash
env:
NMP_E2E_CLUSTER_URL: ${{ env.NMP_E2E_CLUSTER_URL }}
Expand Down
156 changes: 133 additions & 23 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -430,11 +430,11 @@ jobs:
- name: Setup Kind cluster with NeMo Platform
uses: ./.github/actions/setup-kind-cluster
with:
kind_cluster_name: ${{ env.KIND_CLUSTER_NAME }}
image_registry: ${{ needs.build-cpu-smoke-images.outputs.image_registry }}
image_tag: ${{ needs.build-cpu-smoke-images.outputs.image_tag }}
kind_image_pull_token: ${{ github.token }}
kind_image_pull_user: ${{ github.actor }}
kind-cluster-name: ${{ env.KIND_CLUSTER_NAME }}
image-registry: ${{ needs.build-cpu-smoke-images.outputs.image_registry }}
image-tag: ${{ needs.build-cpu-smoke-images.outputs.image_tag }}
kind-image-pull-token: ${{ github.token }}
kind-image-pull-user: ${{ github.actor }}

- name: Run CPU job e2e smoke test
shell: bash
Expand Down Expand Up @@ -513,11 +513,11 @@ jobs:
- name: Setup Kind cluster with NeMo Platform
uses: ./.github/actions/setup-kind-cluster
with:
kind_cluster_name: ${{ env.KIND_CLUSTER_NAME }}
image_registry: ${{ needs.build-cpu-smoke-images.outputs.image_registry }}
image_tag: ${{ needs.build-cpu-smoke-images.outputs.image_tag }}
kind_image_pull_token: ${{ github.token }}
kind_image_pull_user: ${{ github.actor }}
kind-cluster-name: ${{ env.KIND_CLUSTER_NAME }}
image-registry: ${{ needs.build-cpu-smoke-images.outputs.image_registry }}
image-tag: ${{ needs.build-cpu-smoke-images.outputs.image_tag }}
kind-image-pull-token: ${{ github.token }}
kind-image-pull-user: ${{ github.actor }}

- name: Run jobs and data-designer e2e tests
shell: bash
Expand Down Expand Up @@ -949,61 +949,171 @@ jobs:
coverage.xml
coverage.json

python-auth-idp-test:
name: Python auth-idp tests
needs: [changes, policy-wasm, build-cpu-smoke-images]
python-auth-idp-static-test:
name: Python auth-idp static tests
needs: [changes]
if: >
!cancelled() && (
github.event_name == 'workflow_dispatch' ||
needs.changes.outputs.cpu-smoke == 'true' ||
needs.changes.outputs.auth-idp == 'true'
)
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout code
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false
- name: Install uv
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0
with:
python-version: "3.11"
enable-cache: true
cache-dependency-glob: uv.lock
- name: Run auth-idp static tests
run: |
helm dependency build k8s/helm
helm dependency build contrib/auth/authentik/helm
uv run --frozen pytest tests/auth_idp/static -v
env:
_TYPER_FORCE_DISABLE_TERMINAL: "1"
- name: Upload test artifacts
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: python-auth-idp-static-test-results
retention-days: 30
if-no-files-found: ignore
path: |
report.xml
coverage.xml
coverage.json

python-auth-idp-e2e-test:
name: Python auth-idp ${{ matrix.runtime }} tests
needs: [changes, policy-wasm, build-cpu-smoke-images, python-auth-idp-static-test]
if: >
!cancelled() && (
github.event_name == 'workflow_dispatch' ||
needs.changes.outputs.cpu-smoke == 'true' ||
needs.changes.outputs.auth-idp == 'true'
) &&
needs.policy-wasm.result == 'success' &&
needs.build-cpu-smoke-images.result == 'success'
needs.build-cpu-smoke-images.result == 'success' &&
needs.build-cpu-smoke-images.outputs.publish_images == 'true' &&
needs.python-auth-idp-static-test.result == 'success'
Comment thread
coderabbitai[bot] marked this conversation as resolved.
runs-on: ubuntu-latest
Comment thread
coderabbitai[bot] marked this conversation as resolved.
timeout-minutes: 90
permissions:
contents: read
packages: read
strategy:
fail-fast: false
matrix:
include:
- provider: authentik
runtime: authentik-compose
backend: compose
command: compose
- provider: authentik
runtime: authentik-kubernetes
backend: kubernetes
command: k8s
env:
NMP_AUTHENTIK_K8S_RUNTIME: kind
NMP_AUTHENTIK_K8S_NAMESPACE: nemo-authentik
NMP_AUTHENTIK_K8S_IMAGE_PULL_SECRET: ghcr-pull
NMP_AUTHENTIK_K8S_NGC_EXISTING_SECRET: ngc-api
NMP_AUTHENTIK_K8S_CLUSTER_NAME: gha-${{ github.run_id }}-${{ github.run_attempt }}-${{ matrix.runtime }}
NMP_AUTHENTIK_K8S_REUSE_CLUSTER: "1"
steps:
- name: Checkout code
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false
- name: Free disk space
uses: ./.github/actions/free-disk-space
- name: Download policy WASM
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: policy-wasm
path: services/core/auth/src/nmp/core/auth/assets
- name: Install uv
uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0
with:
python-version: "3.11"
enable-cache: true
cache-dependency-glob: uv.lock
- name: Setup Kind cluster
if: matrix.backend == 'kubernetes'
uses: ./.github/actions/setup-kind-cluster
with:
kind-cluster-name: ${{ env.NMP_AUTHENTIK_K8S_CLUSTER_NAME }}
install-nemo-platform: "false"
kube-namespace: ${{ env.NMP_AUTHENTIK_K8S_NAMESPACE }}
image-registry: ${{ needs.build-cpu-smoke-images.outputs.image_registry }}
image-tag: ${{ needs.build-cpu-smoke-images.outputs.image_tag }}
kind-image-pull-token: ${{ github.token }}
kind-image-pull-user: ${{ github.actor }}
- name: Log in to GHCR
if: needs.build-cpu-smoke-images.outputs.publish_images == 'true'
if: matrix.backend == 'compose' && needs.build-cpu-smoke-images.outputs.publish_images == 'true'
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ github.token }}
- name: Run auth-idp tests
run: make test-auth-idp
- name: Install Helm
if: matrix.backend == 'kubernetes'
uses: azure/setup-helm@dda3372f752e03dde6b3237bc9431cdc2f7a02a2 # v5.0.0
- name: Lint Authentik umbrella Helm chart
if: matrix.provider == 'authentik' && matrix.backend == 'kubernetes'
shell: bash
run: |
helm repo add authentik https://charts.goauthentik.io --force-update
Comment thread
crookedstorm marked this conversation as resolved.
helm dependency build k8s/helm
helm dependency build contrib/auth/authentik/helm
helm lint --strict contrib/auth/authentik/helm
- name: Verify official Authentik Helm chart is reachable
if: matrix.provider == 'authentik' && matrix.backend == 'kubernetes'
shell: bash
run: |
helm show chart authentik --repo https://charts.goauthentik.io --version 2026.5.4
- name: Download policy WASM
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: policy-wasm
path: services/core/auth/src/nmp/core/auth/assets
- name: Run auth-idp ${{ matrix.runtime }} tests
run: >
contrib/auth/${{ matrix.provider }}/run.sh
${{ matrix.command }}
--image "${IMAGE_REGISTRY}/nmp-api:${BAKE_TAG}"
env:
_TYPER_FORCE_DISABLE_TERMINAL: "1"
E2E_SERVICES_LOG_DIR: ${{ runner.temp }}/e2e-services-logs
IMAGE_REGISTRY: ${{ needs.build-cpu-smoke-images.outputs.image_registry }}
BAKE_TAG: ${{ needs.build-cpu-smoke-images.outputs.image_tag }}
NMP_AUTHENTIK_K8S_JUNIT_XML: report-auth-idp-${{ matrix.runtime }}.xml
NMP_AUTHENTIK_K8S_IMAGE_PULL_SECRET: ${{ env.NMP_AUTHENTIK_K8S_IMAGE_PULL_SECRET }}
NMP_AUTHENTIK_K8S_SKIP_IMAGE_LOAD: ${{ needs.build-cpu-smoke-images.outputs.publish_images == 'true' && '1' || '0' }}
- name: Collect Kubernetes logs
if: always() && matrix.backend == 'kubernetes'
shell: bash
run: e2e/k8s/scripts/collect_k8s_logs.sh
- name: Upload test artifacts
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: python-auth-idp-test-results
name: python-auth-idp-${{ matrix.runtime }}-test-results
retention-days: 30
if-no-files-found: ignore
path: |
k8s-logs/
report-auth-idp-${{ matrix.runtime }}.xml
${{ runner.temp }}/e2e-services-logs/
- name: Delete kind cluster
if: always() && matrix.backend == 'kubernetes'
shell: bash
run: |
docker rm -f "cloud-provider-kind-${NMP_AUTHENTIK_K8S_CLUSTER_NAME}" || true
kind delete cluster --name "${NMP_AUTHENTIK_K8S_CLUSTER_NAME}" || true

# Build wheels for all packages × python versions. Downstream jobs
# (wheel-test, python-e2e-test) download these artifacts instead
Expand Down
4 changes: 0 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,6 @@ docs-watch: ## Start Fern docs dev plus a repo-level watcher for docs/** changes
docs-check: ## Validate the Fern docs (fern check + validate-mdx + gated-link check)
cd docs/fern && npm run check

.PHONY: test-auth-idp
test-auth-idp: ## Run the auth-idp test suite
bash contrib/auth/authentik/run.sh test $(ARGS)

.PHONY: docs-check-python-snippets
docs-check-python-snippets: ## Syntax-check and type-check Python snippets in one doc (DOCS_PATH=...)
@if [ -z "$(strip $(DOCS_PATH))" ]; then echo "Usage: make docs-check-python-snippets DOCS_PATH=docs/customizer/tutorials/import-hf-model.mdx" >&2; exit 2; fi
Expand Down
6 changes: 5 additions & 1 deletion conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,8 @@ def pytest_collection_modifyitems(config, items):
"unit",
"e2e",
"auth_idp",
"auth_idp_docker",
"auth_idp_k8s",
"smoke_gpu_tasks",
"smoke_nmp_customizer_tasks",
"smoke_nmp_automodel_training",
Expand Down Expand Up @@ -308,7 +310,9 @@ def pytest_runtest_setup(item):
if not item.config.getoption("--run-slow"):
skip_test("Skipping slow test (use --run-slow to run)")
if "e2e" in [marker.name for marker in item.iter_markers()]:
if not item.config.getoption("--run-e2e"):
auth_idp_runtime = item.config.getoption("--auth-idp-runtime", default=None)
auth_idp_runtime_selected = auth_idp_runtime and "auth_idp" in [marker.name for marker in item.iter_markers()]
if not item.config.getoption("--run-e2e") and not auth_idp_runtime_selected:
skip_test("Skipping e2e test (use --run-e2e to run)")
if "subprocess_only" in [marker.name for marker in item.iter_markers()]:
if os.environ.get("NMP_BASE_URL"):
Expand Down
3 changes: 3 additions & 0 deletions contrib/auth/authentik/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.generated/
helm/Chart.lock
helm/charts/
Loading
Loading