diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..b0de9e1 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,88 @@ +--- +name: Bug Report +about: Report a bug to help us improve +title: '[BUG] ' +labels: bug +assignees: '' +--- + +## Bug Description + +A clear and concise description of what the bug is. + +## Environment + +- **Operator Version**: [e.g., v0.1.0] +- **Kubernetes Version**: [e.g., v1.31.13] +- **Cloud Provider**: [e.g., AWS EKS, GKE, AKS, k0s] +- **OS**: [e.g., Ubuntu 22.04] +- **Deployment Method**: [e.g., Helm, YAML manifests, Kustomize] + +## Steps to Reproduce + +1. Deploy operator with '...' +2. Apply CRD '...' +3. Observe error '...' +4. See error + +## Expected Behavior + +A clear and concise description of what you expected to happen. + +## Actual Behavior + +A clear and concise description of what actually happened. + +## Logs + +
+Operator Logs + +``` +Paste operator pod logs here: +kubectl logs -n splunk-ai-operator-system -l app.kubernetes.io/name=splunk-ai-operator +``` + +
+ +
+Resource Status + +``` +Paste relevant resource status here: +kubectl describe aiplatform -n +``` + +
+ +## Configuration + +
+AIPlatform YAML + +```yaml +# Paste your AIPlatform or relevant CRD YAML here +``` + +
+ +
+Helm Values (if using Helm) + +```yaml +# Paste your custom Helm values here +``` + +
+ +## Additional Context + +Add any other context about the problem here, such as: +- Recent changes to your cluster +- Related issues or PRs +- Workarounds you've tried +- Screenshots (if applicable) + +## Possible Solution + +If you have an idea of what might be causing the issue or how to fix it, please share it here. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..f868735 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,14 @@ +blank_issues_enabled: true +contact_links: + - name: Ask a Question + url: https://github.com/splunk/splunk-ai-operator/discussions + about: Ask questions and discuss ideas with the community + - name: Security Vulnerability + url: https://github.com/splunk/splunk-ai-operator/security/advisories/new + about: Report security vulnerabilities privately + - name: Documentation + url: https://github.com/splunk/splunk-ai-operator/tree/main/docs + about: Read the full documentation + - name: Splunk Support + url: mailto:splunkai@cisco.com + about: Contact the maintainers directly diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..70fe1b8 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,75 @@ +--- +name: Feature Request +about: Suggest a new feature or enhancement +title: '[FEATURE] ' +labels: enhancement +assignees: '' +--- + +## Feature Description + +A clear and concise description of the feature you'd like to see. + +## Problem Statement + +What problem does this feature solve? Why is this feature needed? + +**Example**: "I want to be able to [...] so that I can [...]" + +## Proposed Solution + +Describe how you envision this feature working. Include: +- API changes (if applicable) +- Configuration options +- User workflow +- Example usage + +### Example Configuration + +```yaml +# Example of how the feature would be used +apiVersion: ai.splunk.com/v1 +kind: AIPlatform +metadata: + name: example +spec: + # New feature configuration here + newFeature: + enabled: true + option: value +``` + +## Alternatives Considered + +Describe any alternative solutions or features you've considered. Why would the proposed solution be better? + +## Use Case + +Describe your specific use case for this feature. Include: +- Your environment (cloud provider, cluster size, etc.) +- What you're trying to accomplish +- How this feature would improve your workflow + +## Impact + +- **Who would benefit**: [e.g., all users, users with GPU workloads, multi-tenant deployments] +- **Priority**: [e.g., nice-to-have, important, critical] +- **Urgency**: [e.g., can wait, needed soon, blocking] + +## Additional Context + +Add any other context, screenshots, diagrams, or examples about the feature request here. + +## Related Issues/PRs + +- Related to #XXX +- Similar to #YYY +- Depends on #ZZZ + +## Willingness to Contribute + +Are you willing to contribute to the implementation of this feature? +- [ ] Yes, I can submit a PR +- [ ] Yes, with guidance +- [ ] No, but I can test +- [ ] No, just suggesting diff --git a/.github/ct-config.yaml b/.github/ct-config.yaml new file mode 100644 index 0000000..d879a79 --- /dev/null +++ b/.github/ct-config.yaml @@ -0,0 +1,33 @@ +# Configuration for chart-testing (ct) +--- +# Helm chart directories +chart-dirs: + - helm-chart + +# Chart repositories for dependency resolution +chart-repos: + - jetstack=https://charts.jetstack.io + - prometheus-community=https://prometheus-community.github.io/helm-charts + - opentelemetry=https://open-telemetry.github.io/opentelemetry-helm-charts + - kuberay=https://ray-project.github.io/kuberay-helm + +# Target branch for comparison (used in PRs) +target-branch: main + +# Upgrade testing +upgrade: true + +# Skip missing values files +skip-missing-values: true + +# Validate maintainers field in Chart.yaml +validate-maintainers: true + +# Validate chart version bump +check-version-increment: true + +# Helm extra arguments +helm-extra-args: --timeout 5m + +# Excluded charts (if any) +excluded-charts: [] diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..9dea9c8 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,46 @@ +version: 2 +updates: + # Go dependencies + - package-ecosystem: "gomod" + directory: "/" + schedule: + interval: "weekly" + day: "monday" + time: "09:00" + open-pull-requests-limit: 10 + labels: + - "dependencies" + - "go" + commit-message: + prefix: "chore(deps)" + include: "scope" + + # GitHub Actions + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + day: "monday" + time: "09:00" + open-pull-requests-limit: 10 + labels: + - "dependencies" + - "github-actions" + commit-message: + prefix: "chore(deps)" + include: "scope" + + # Docker (for Dockerfiles) + - package-ecosystem: "docker" + directory: "/" + schedule: + interval: "weekly" + day: "monday" + time: "09:00" + open-pull-requests-limit: 5 + labels: + - "dependencies" + - "docker" + commit-message: + prefix: "chore(deps)" + include: "scope" diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..d5669af --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,108 @@ +## Description + + + +## Related Issues + + + + +- Related to # + +## Type of Change + + + +- [ ] Bug fix (non-breaking change which fixes an issue) +- [ ] New feature (non-breaking change which adds functionality) +- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) +- [ ] Documentation update +- [ ] Refactoring (no functional changes) +- [ ] Performance improvement +- [ ] Test improvement +- [ ] CI/CD improvement +- [ ] Chore (dependency updates, etc.) + +## Changes Made + + + +- +- +- + +## Testing Performed + + + +- [ ] Unit tests pass (`make test`) +- [ ] Linting passes (`make lint`) +- [ ] Integration tests pass (if applicable) +- [ ] E2E tests pass (if applicable) +- [ ] Manual testing performed + +### Test Environment + +- **Kubernetes Version**: +- **Cloud Provider**: +- **Deployment Method**: + +### Test Steps + +1. +2. +3. + +## Documentation + + + +- [ ] Updated inline code comments +- [ ] Updated README.md (if adding features) +- [ ] Updated API documentation +- [ ] Updated deployment guides +- [ ] Updated CHANGELOG.md +- [ ] No documentation needed + +## Checklist + + + +- [ ] My code follows the project's style guidelines +- [ ] I have performed a self-review of my code +- [ ] I have commented my code, particularly in hard-to-understand areas +- [ ] I have made corresponding changes to the documentation +- [ ] My changes generate no new warnings +- [ ] I have added tests that prove my fix is effective or that my feature works +- [ ] New and existing unit tests pass locally with my changes +- [ ] Any dependent changes have been merged and published +- [ ] I have updated the Helm chart version (if applicable) +- [ ] I have updated CRD schemas (if applicable) + +## Breaking Changes + + + +**Impact**: + +**Migration Path**: + +## Screenshots/Recordings + + + +## Additional Notes + + + +## Reviewer Notes + + + +Please pay special attention to: +- +- + +--- + +**Commit Message Convention**: This PR follows [Conventional Commits](https://www.conventionalcommits.org/) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 0000000..e83830f --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -0,0 +1,67 @@ +name: "CodeQL Advanced" + +# ⚠️ TEMPORARY STATE: Upload disabled to prevent conflicts +# This workflow runs but doesn't upload results until GitHub default setup is disabled +# +# CURRENT: GitHub's default CodeQL is active (provides basic scanning) +# FUTURE: To use this advanced workflow with custom queries: +# 1. Go to: Settings → Code security and analysis → Code scanning +# 2. Under "CodeQL analysis", change from "Default" to "Advanced" +# 3. Update line 55: upload: false → upload: true +# 4. Remove line 57: continue-on-error: true +# +# Benefits of custom workflow (after enabling): +# - Enhanced queries (+security-and-quality) +# - Weekly scheduled scans +# - More configuration control + +on: + push: + branches: [ "main", "develop" ] + pull_request: + branches: [ "main", "develop" ] + schedule: + - cron: '30 1 * * 1' # Run every Monday at 1:30 AM UTC + +permissions: + actions: read + contents: read + security-events: write + +jobs: + analyze: + name: Analyze (${{ matrix.language }}) + runs-on: ubuntu-latest + timeout-minutes: 360 + strategy: + fail-fast: false + matrix: + include: + - language: go + build-mode: autobuild + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v4 + with: + languages: ${{ matrix.language }} + build-mode: ${{ matrix.build-mode }} + queries: +security-and-quality + + - if: matrix.build-mode == 'manual' + name: Manual Build + shell: bash + run: | + echo 'Manual build not required for Go with autobuild' + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v4 + with: + category: "/language:${{ matrix.language }}" + output: sarif-results + upload: false # Disabled: conflicts with default setup + # Set to 'true' after disabling GitHub's default CodeQL setup + continue-on-error: true # Don't fail workflow if upload conflicts diff --git a/.github/workflows/helm-lint-test.yml b/.github/workflows/helm-lint-test.yml new file mode 100644 index 0000000..7ff11b0 --- /dev/null +++ b/.github/workflows/helm-lint-test.yml @@ -0,0 +1,203 @@ +name: Helm Chart Lint and Test + +on: + workflow_call: + # Can be called from other workflows + pull_request: + paths: + - 'helm-chart/**' + - '.github/workflows/helm-lint-test.yml' + push: + branches: + - main + - develop + paths: + - 'helm-chart/**' + +jobs: + lint-test: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Helm + uses: azure/setup-helm@v4 + with: + version: 'v3.14.0' + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Set up chart-testing + uses: helm/chart-testing-action@v2.6.1 + + - name: Add Helm repositories + run: | + helm repo add jetstack https://charts.jetstack.io + helm repo add prometheus-community https://prometheus-community.github.io/helm-charts + helm repo add opentelemetry https://open-telemetry.github.io/opentelemetry-helm-charts + helm repo add kuberay https://ray-project.github.io/kuberay-helm + helm repo update + + - name: Lint splunk-ai-operator chart + run: | + echo "::group::Linting splunk-ai-operator" + helm lint helm-chart/splunk-ai-operator + echo "::endgroup::" + + - name: Lint splunk-ai-platform chart + run: | + echo "::group::Linting splunk-ai-platform" + # Update dependencies first + helm dependency update helm-chart/splunk-ai-platform + helm lint helm-chart/splunk-ai-platform + echo "::endgroup::" + + - name: Template splunk-ai-operator chart + run: | + echo "::group::Templating splunk-ai-operator" + helm template test-release helm-chart/splunk-ai-operator \ + --namespace splunk-ai-operator-system \ + --create-namespace \ + --debug > /tmp/operator-template.yaml + echo "Chart templates generated successfully" + echo "::endgroup::" + + - name: Template splunk-ai-platform chart + run: | + echo "::group::Templating splunk-ai-platform" + helm template test-release helm-chart/splunk-ai-platform \ + --namespace ai-platform \ + --create-namespace \ + --debug > /tmp/platform-template.yaml + echo "Chart templates generated successfully" + echo "::endgroup::" + + - name: Validate Kubernetes manifests + run: | + echo "::group::Validating Kubernetes manifests" + # Install kubeval + curl -sSL https://github.com/instrumenta/kubeval/releases/latest/download/kubeval-linux-amd64.tar.gz | tar xz + sudo mv kubeval /usr/local/bin + + # Validate operator manifests + echo "Validating operator manifests..." + if kubeval --strict --ignore-missing-schemas /tmp/operator-template.yaml 2>&1 | tee /tmp/operator-kubeval.log; then + echo "✅ Operator manifests validation passed" + else + echo "❌ Operator manifests validation failed" + cat /tmp/operator-kubeval.log + exit 1 + fi + + # Validate platform manifests + echo "Validating platform manifests..." + if kubeval --strict --ignore-missing-schemas /tmp/platform-template.yaml 2>&1 | tee /tmp/platform-kubeval.log; then + echo "✅ Platform manifests validation passed" + else + echo "❌ Platform manifests validation failed" + cat /tmp/platform-kubeval.log + exit 1 + fi + echo "::endgroup::" + + - name: Check for chart version bump (PR only) + if: github.event_name == 'pull_request' + run: | + echo "::group::Checking version bump" + + # Get the chart versions from main branch + git fetch origin main:main + OPERATOR_VERSION_MAIN=$(git show main:helm-chart/splunk-ai-operator/Chart.yaml | grep '^version:' | awk '{print $2}' | tr -d '"') + PLATFORM_VERSION_MAIN=$(git show main:helm-chart/splunk-ai-platform/Chart.yaml | grep '^version:' | awk '{print $2}' | tr -d '"') + + # Get current chart versions + OPERATOR_VERSION_CURRENT=$(grep '^version:' helm-chart/splunk-ai-operator/Chart.yaml | awk '{print $2}' | tr -d '"') + PLATFORM_VERSION_CURRENT=$(grep '^version:' helm-chart/splunk-ai-platform/Chart.yaml | awk '{print $2}' | tr -d '"') + + echo "Operator chart version: $OPERATOR_VERSION_MAIN → $OPERATOR_VERSION_CURRENT" + echo "Platform chart version: $PLATFORM_VERSION_MAIN → $PLATFORM_VERSION_CURRENT" + + # Check if versions were bumped + if [ "$OPERATOR_VERSION_MAIN" = "$OPERATOR_VERSION_CURRENT" ] && [ "$PLATFORM_VERSION_MAIN" = "$PLATFORM_VERSION_CURRENT" ]; then + echo "⚠️ WARNING: Chart versions were not bumped" + echo "::warning::Chart versions should be incremented when making changes" + else + echo "✅ Chart versions were bumped" + fi + echo "::endgroup::" + + - name: Run chart-testing (ct lint) + run: | + echo "::group::Running ct lint" + ct lint --config .github/ct-config.yaml --charts helm-chart/splunk-ai-operator,helm-chart/splunk-ai-platform || true + echo "::endgroup::" + + - name: Create kind cluster for testing + uses: helm/kind-action@v1.10.0 + with: + cluster_name: helm-test + wait: 5m + + # Note: Helm install/upgrade tests use --dry-run because: + # 1. Images may not be publicly available yet (pre-release) + # 2. Operator requires external dependencies (cert-manager, etc.) + # 3. Dry-run validates chart structure and manifest generation + # Full E2E tests with actual installation are in test/e2e/ + + - name: Install CRDs + run: | + echo "::group::Installing CRDs" + # Install cert-manager CRDs + kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.14.0/cert-manager.crds.yaml + + # Install prometheus operator CRDs + kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/main/example/prometheus-operator-crd/monitoring.coreos.com_servicemonitors.yaml + kubectl apply --server-side -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/main/example/prometheus-operator-crd/monitoring.coreos.com_podmonitors.yaml + + # Install OpenTelemetry CRDs + kubectl apply -f https://github.com/open-telemetry/opentelemetry-operator/releases/download/v0.102.0/opentelemetry-operator.yaml || true + + echo "CRDs installed successfully" + echo "::endgroup::" + + - name: Test install splunk-ai-operator chart (dry-run) + run: | + echo "::group::Testing splunk-ai-operator installation (dry-run)" + # Use dry-run to test chart installation without pulling images + # This validates the Helm chart structure and Kubernetes manifests + helm install test-operator helm-chart/splunk-ai-operator \ + --namespace splunk-ai-operator-system \ + --create-namespace \ + --dry-run \ + --debug \ + --set image.repository=ghcr.io/splunk/splunk-ai-operator \ + --set image.tag=0.1.0 + + echo "✅ Dry-run installation successful" + echo "::endgroup::" + + - name: Test upgrade splunk-ai-operator chart (dry-run) + run: | + echo "::group::Testing splunk-ai-operator upgrade (dry-run)" + helm upgrade test-operator helm-chart/splunk-ai-operator \ + --namespace splunk-ai-operator-system \ + --install \ + --dry-run \ + --debug \ + --set image.repository=ghcr.io/splunk/splunk-ai-operator \ + --set image.tag=0.1.0 + + echo "✅ Dry-run upgrade successful" + echo "::endgroup::" + + - name: Cleanup + if: always() + run: | + helm list --all-namespaces + kubectl get all --all-namespaces diff --git a/.github/workflows/main-build-image.yml b/.github/workflows/main-build-image.yml index 0bfb86e..45a1739 100644 --- a/.github/workflows/main-build-image.yml +++ b/.github/workflows/main-build-image.yml @@ -2,29 +2,50 @@ name: Build and Push Image on: workflow_call: +permissions: + contents: read + packages: write + id-token: write # Required for artifact attestation + attestations: write # Required for artifact attestation + jobs: build: runs-on: ubuntu-latest env: - SPLUNK_AI_OPERATOR_IMAGE_NAME: splunk/splunk-ai-operator - ECR_REPOSITORY: ${{ secrets.ECR_REPOSITORY }} - S3_REGION: us-west-2 + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} steps: - - name: Set up cosign - uses: sigstore/cosign-installer@main - name: Checkout code - uses: actions/checkout@v2 - - name: Dotenv Action - uses: falti/dotenv-action@d4d12eaa0e1dd06d5bdc3d7af3bf4c8c93cb5359 + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Read .env file id: dotenv + run: | + if [ -f .env ]; then + while IFS='=' read -r key value; do + # Skip comments and empty lines + [[ "$key" =~ ^#.*$ ]] && continue + [[ -z "$key" ]] && continue + # Remove quotes and export + value=$(echo "$value" | sed -e 's/^\"//' -e 's/\"$//' -e "s/^'//" -e "s/'$//") + echo "$key=$value" >> $GITHUB_OUTPUT + done < .env + fi + - name: Setup Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v5 with: go-version: ${{ steps.dotenv.outputs.GO_VERSION }} + cache: true + - name: Install Ginkgo run: make setup/ginkgo + - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2.5.0 + uses: docker/setup-buildx-action@v3 + - name: Install Operator SDK run: | export ARCH=$(case $(uname -m) in x86_64) echo -n amd64 ;; aarch64) echo -n arm64 ;; *) echo -n $(uname -m) ;; esac) @@ -33,14 +54,45 @@ jobs: sudo curl -LO ${OPERATOR_SDK_DL_URL}/operator-sdk_${OS}_${ARCH} sudo chmod +x operator-sdk_${OS}_${ARCH} sudo mv operator-sdk_${OS}_${ARCH} /usr/local/bin/operator-sdk - - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@v1 + + - name: Log in to GitHub Container Registry + uses: docker/login-action@v3 with: - aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - aws-region: ${{ secrets.AWS_DEFAULT_REGION }} - - name: Login to Amazon ECR - uses: aws-actions/amazon-ecr-login@v1 - - name: Build and push Splunk AI Operator Image - run: | - make docker-buildx IMG=${{ secrets.ECR_REPOSITORY }}/${{ env.SPLUNK_AI_OPERATOR_IMAGE_NAME }}:$GITHUB_SHA + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata (tags, labels) + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=ref,event=branch + type=ref,event=pr + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=sha + type=raw,value=latest,enable={{is_default_branch}} + + - name: Build and push image + id: build + uses: docker/build-push-action@v5 + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max + platforms: linux/amd64 + + - name: Generate artifact attestation + # Only run attestation for non-fork PRs and direct pushes + # Fork PRs don't have access to id-token which is required for attestations + if: github.event.pull_request.head.repo.full_name == github.repository || github.event_name != 'pull_request' + uses: actions/attest-build-provenance@v1 + with: + subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + subject-digest: ${{ steps.build.outputs.digest }} + push-to-registry: true diff --git a/.github/workflows/main-check-formatting.yml b/.github/workflows/main-check-formatting.yml index 0a93045..94e6419 100644 --- a/.github/workflows/main-check-formatting.yml +++ b/.github/workflows/main-check-formatting.yml @@ -6,11 +6,31 @@ jobs: check: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: falti/dotenv-action@d4d12eaa0e1dd06d5bdc3d7af3bf4c8c93cb5359 + - name: Checkout code + uses: actions/checkout@v4 + + - name: Read .env file id: dotenv - - uses: actions/setup-go@v2 + run: | + if [ -f .env ]; then + while IFS='=' read -r key value; do + # Skip comments and empty lines + [[ "$key" =~ ^#.*$ ]] && continue + [[ -z "$key" ]] && continue + # Remove quotes and export + value=$(echo "$value" | sed -e 's/^"//' -e 's/"$//' -e "s/^'//" -e "s/'$//") + echo "$key=$value" >> $GITHUB_OUTPUT + done < .env + fi + + - name: Setup Go + uses: actions/setup-go@v5 with: go-version: ${{ steps.dotenv.outputs.GO_VERSION }} - - run: make fmt && if [[ $? -ne 0 ]]; then false; fi - - run: make vet && if [[ $? -ne 0 ]]; then false; fi + cache: true + + - name: Check formatting + run: make fmt && if [[ $? -ne 0 ]]; then false; fi + + - name: Run vet + run: make vet && if [[ $? -ne 0 ]]; then false; fi diff --git a/.github/workflows/main-unit-tests.yml b/.github/workflows/main-unit-tests.yml index 3ae332b..26dd4ae 100644 --- a/.github/workflows/main-unit-tests.yml +++ b/.github/workflows/main-unit-tests.yml @@ -6,12 +6,28 @@ jobs: test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: falti/dotenv-action@d4d12eaa0e1dd06d5bdc3d7af3bf4c8c93cb5359 + - name: Checkout code + uses: actions/checkout@v4 + + - name: Read .env file id: dotenv - - uses: actions/setup-go@v2 + run: | + if [ -f .env ]; then + while IFS='=' read -r key value; do + # Skip comments and empty lines + [[ "$key" =~ ^#.*$ ]] && continue + [[ -z "$key" ]] && continue + # Remove quotes and export + value=$(echo "$value" | sed -e 's/^"//' -e 's/"$//' -e "s/^'//" -e "s/'$//") + echo "$key=$value" >> $GITHUB_OUTPUT + done < .env + fi + + - name: Setup Go + uses: actions/setup-go@v5 with: go-version: ${{ steps.dotenv.outputs.GO_VERSION }} + cache: true - name: Run Unit Tests with Coverage run: | go install github.com/mattn/goveralls@latest diff --git a/.github/workflows/main-vulnerability-scan.yml b/.github/workflows/main-vulnerability-scan.yml index 5ea0704..eb696cb 100644 --- a/.github/workflows/main-vulnerability-scan.yml +++ b/.github/workflows/main-vulnerability-scan.yml @@ -2,38 +2,62 @@ name: Vulnerability Scan on: workflow_call: +permissions: + actions: read + contents: read + packages: read + security-events: write + jobs: scan: - permissions: - actions: read - contents: read - security-events: write runs-on: ubuntu-latest env: - IMAGE_NAME: ${{ secrets.ECR_REPOSITORY }}/splunk/splunk-ai-operator:${{ github.sha }} + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} steps: - - uses: sigstore/cosign-installer@main - - uses: actions/checkout@v2 - - uses: falti/dotenv-action@d4d12eaa0e1dd06d5bdc3d7af3bf4c8c93cb5359 - id: dotenv - - uses: docker/setup-buildx-action@v2.5.0 - - uses: aws-actions/configure-aws-credentials@v1 + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to GitHub Container Registry + uses: docker/login-action@v3 with: - aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - aws-region: ${{ secrets.AWS_DEFAULT_REGION }} - - uses: aws-actions/amazon-ecr-login@v1 - - name: Pull Splunk AI Operator Image Locally - run: docker pull ${{ env.IMAGE_NAME }} + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Determine image tag + id: image-tag + run: | + # Use short SHA format to match the image tag created by docker/metadata-action + SHORT_SHA=$(echo "${{ github.sha }}" | cut -c1-7) + IMAGE_TAG="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:sha-${SHORT_SHA}" + echo "image-tag=$IMAGE_TAG" >> $GITHUB_OUTPUT + echo "Scanning image: $IMAGE_TAG" + + - name: Pull image locally + run: docker pull ${{ steps.image-tag.outputs.image-tag }} + - name: Run Trivy vulnerability scanner uses: aquasecurity/trivy-action@master with: - image-ref: '${{ env.IMAGE_NAME }}' + image-ref: '${{ steps.image-tag.outputs.image-tag }}' format: sarif - severity: 'CRITICAL' + severity: 'CRITICAL,HIGH' ignore-unfixed: true output: 'trivy-results.sarif' + - name: Upload Trivy scan results to GitHub Security tab uses: github/codeql-action/upload-sarif@v3 with: sarif_file: 'trivy-results.sarif' + + - name: Run Trivy vulnerability scanner (table output) + uses: aquasecurity/trivy-action@master + with: + image-ref: '${{ steps.image-tag.outputs.image-tag }}' + format: table + severity: 'CRITICAL,HIGH' + ignore-unfixed: true diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b6e6db1..2eee6eb 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -9,7 +9,10 @@ on: permissions: actions: read contents: read + packages: write security-events: write + id-token: write # Required for artifact attestation + attestations: write # Required for artifact attestation jobs: check-formatting: @@ -29,6 +32,10 @@ jobs: secrets: inherit needs: build-image + helm-lint-test: + uses: ./.github/workflows/helm-lint-test.yml + needs: unit-tests # Run in parallel with build-image + # smoke-tests: # uses: ./.github/workflows/main-smoke-tests.yml # secrets: inherit diff --git a/.github/workflows/prerelease-update-versions.yml b/.github/workflows/prerelease-update-versions.yml index 0064878..290d1b8 100644 --- a/.github/workflows/prerelease-update-versions.yml +++ b/.github/workflows/prerelease-update-versions.yml @@ -11,20 +11,35 @@ jobs: pull-requests: write steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v4 + - name: Deep Fetch run: | git fetch --prune --unshallow + - name: Create ChangeLog since last release run: | git log $(git describe --tags --abbrev=0)..HEAD --oneline >> docs/ChangeLog-NEW.md - - name: Dotenv Action - uses: falti/dotenv-action@d4d12eaa0e1dd06d5bdc3d7af3bf4c8c93cb5359 + + - name: Read .env file id: dotenv + run: | + if [ -f .env ]; then + while IFS='=' read -r key value; do + # Skip comments and empty lines + [[ "$key" =~ ^#.*$ ]] && continue + [[ -z "$key" ]] && continue + # Remove quotes and export + value=$(echo "$value" | sed -e 's/^"//' -e 's/"$//' -e "s/^'//" -e "s/'$//") + echo "$key=$value" >> $GITHUB_OUTPUT + done < .env + fi + - name: Setup Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v5 with: go-version: ${{ steps.dotenv.outputs.GO_VERSION }} + cache: true - name: Update Helm Version if: github.event.inputs.old_operator_version != github.event.inputs.new_operator_version uses: jacobtomlinson/gha-find-replace@v3 diff --git a/.github/workflows/release-package-helm.yml b/.github/workflows/release-package-helm.yml index 6e3a0c0..26716b2 100644 --- a/.github/workflows/release-package-helm.yml +++ b/.github/workflows/release-package-helm.yml @@ -1,29 +1,143 @@ -name: Package Helm Chart +name: Package and Release Helm Charts on: workflow_call: + inputs: + old_operator_version: + description: 'OLD OPERATOR VERSION' + required: false + type: string + new_operator_version: + description: 'NEW OPERATOR VERSION' + required: true + type: string + push: + tags: + - 'v*.*.*' jobs: package: runs-on: ubuntu-latest permissions: - # Need the write permission because this job commits changes to some folders like dist contents: write - pull-requests: write steps: - name: Checkout code - uses: actions/checkout@v2 - - name: Dotenv Action - uses: falti/dotenv-action@d4d12eaa0e1dd06d5bdc3d7af3bf4c8c93cb5359 - id: dotenv - - name: Setup Go - uses: actions/setup-go@v2 + uses: actions/checkout@v4 with: - go-version: ${{ steps.dotenv.outputs.GO_VERSION }} - - name: Run helm chart package creation + fetch-depth: 0 + + - name: Install Helm + uses: azure/setup-helm@v4 + with: + version: 'v3.14.0' + + - name: Extract version + id: version + run: | + if [ "${{ github.event_name }}" == "push" ] && [[ "${{ github.ref }}" == refs/tags/* ]]; then + # Extract from git tag (remove 'v' prefix) + VERSION=${GITHUB_REF_NAME#v} + elif [ -n "${{ inputs.new_operator_version }}" ]; then + # Use input version (for workflow_call) + VERSION="${{ inputs.new_operator_version }}" + else + # Fallback to Chart.yaml version + VERSION=$(grep '^version:' helm-chart/splunk-ai-operator/Chart.yaml | awk '{print $2}' | tr -d '"') + fi + echo "version=$VERSION" >> $GITHUB_OUTPUT + echo "Packaging version: $VERSION" + + - name: Update Chart versions + run: | + VERSION="${{ steps.version.outputs.version }}" + + # Update operator chart + sed -i "s/^version:.*/version: \"$VERSION\"/" helm-chart/splunk-ai-operator/Chart.yaml + sed -i "s/^appVersion:.*/appVersion: \"$VERSION\"/" helm-chart/splunk-ai-operator/Chart.yaml + + # Validate operator chart update + OP_VER=$(grep '^version:' helm-chart/splunk-ai-operator/Chart.yaml | awk '{print $2}' | tr -d '"' | tr -d "'") + OP_APPVER=$(grep '^appVersion:' helm-chart/splunk-ai-operator/Chart.yaml | awk '{print $2}' | tr -d '"' | tr -d "'") + if [ "$OP_VER" != "$VERSION" ] || [ "$OP_APPVER" != "$VERSION" ]; then + echo "ERROR: Failed to update operator chart version/appVersion to $VERSION" + echo "Expected: $VERSION" + echo "Got version: $OP_VER, appVersion: $OP_APPVER" + cat helm-chart/splunk-ai-operator/Chart.yaml + exit 1 + fi + echo "✅ Operator chart updated successfully: version=$OP_VER, appVersion=$OP_APPVER" + + # Update platform chart if it exists + if [ -f helm-chart/splunk-ai-platform/Chart.yaml ]; then + sed -i "s/^version:.*/version: \"$VERSION\"/" helm-chart/splunk-ai-platform/Chart.yaml + sed -i "s/^appVersion:.*/appVersion: \"$VERSION\"/" helm-chart/splunk-ai-platform/Chart.yaml + + # Validate platform chart update + PLAT_VER=$(grep '^version:' helm-chart/splunk-ai-platform/Chart.yaml | awk '{print $2}' | tr -d '"' | tr -d "'") + PLAT_APPVER=$(grep '^appVersion:' helm-chart/splunk-ai-platform/Chart.yaml | awk '{print $2}' | tr -d '"' | tr -d "'") + if [ "$PLAT_VER" != "$VERSION" ] || [ "$PLAT_APPVER" != "$VERSION" ]; then + echo "ERROR: Failed to update platform chart version/appVersion to $VERSION" + echo "Expected: $VERSION" + echo "Got version: $PLAT_VER, appVersion: $PLAT_APPVER" + cat helm-chart/splunk-ai-platform/Chart.yaml + exit 1 + fi + echo "✅ Platform chart updated successfully: version=$PLAT_VER, appVersion=$PLAT_APPVER" + fi + + - name: Package Helm charts + run: | + mkdir -p .helm-releases + + # Package operator chart + helm package helm-chart/splunk-ai-operator --destination .helm-releases + + # Package platform chart if it exists + if [ -f helm-chart/splunk-ai-platform/Chart.yaml ]; then + helm package helm-chart/splunk-ai-platform --destination .helm-releases + fi + + echo "Packaged charts:" + ls -lh .helm-releases/ + + - name: Generate Helm repository index run: | - helm package helm-chart/splunk-ai-operator - cp splunk-ai-operator-${{ github.event.inputs.new_operator_version }}.tgz docs/ - mv splunk-ai-operator-${{ github.event.inputs.new_operator_version }}.tgz helm-chart/splunk-enterprise/charts - helm package helm-chart/splunk-enterprise - mv splunk-enterprise-${{ github.event.inputs.new_operator_version }}.tgz docs/ - helm repo index --url https://splunk.github.io/splunk-ai-operator/ docs/ + RELEASE_TAG="v${{ steps.version.outputs.version }}" + helm repo index .helm-releases \ + --url "https://github.com/${{ github.repository }}/releases/download/${RELEASE_TAG}" + + echo "Generated index.yaml:" + cat .helm-releases/index.yaml + + - name: Create or Update GitHub Release + uses: softprops/action-gh-release@v1 + with: + tag_name: v${{ steps.version.outputs.version }} + files: | + .helm-releases/*.tgz + .helm-releases/index.yaml + generate_release_notes: true + draft: false + prerelease: false + body: | + ## Splunk AI Operator Helm Charts + + This release includes Helm charts for the Splunk AI Operator. + + ### Installation + + #### Direct Install from GitHub Release + ```bash + helm install splunk-ai-operator \ + https://github.com/${{ github.repository }}/releases/download/v${{ steps.version.outputs.version }}/splunk-ai-operator-${{ steps.version.outputs.version }}.tgz + ``` + + #### Using as Helm Repository + ```bash + helm repo add splunk-ai https://github.com/${{ github.repository }}/releases/download/v${{ steps.version.outputs.version }}/ + helm repo update + helm install splunk-ai-operator splunk-ai/splunk-ai-operator --version ${{ steps.version.outputs.version }} + ``` + + See [Helm Deployment Guide](https://github.com/${{ github.repository }}/blob/main/docs/deployment/helm-deployment.md) for detailed instructions. + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 5773dcb..0000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid": "830387 - "version": "0.2.0", - "configurations": [ - { - "name": "Kubernetes: Run/Debug", - "type": "cloudcode.kubernetes", - "request": "launch", - "skaffoldConfig": "${workspaceFolder}/skaffold.yaml", - "watch": true, - "cleanUp": true, - "portForward": true - }, - { - "name": "Launch file", - "type": "go", - "request": "launch", - "mode": "debug", - "program": "${workspaceFolder}/cmd/main.go", - // "envFile": "${workspaceFolder}/.env", - "env": { - "IAC_URL": "test.iac.url", - "API_GATEWAY_HOST": "", // Check if this should be filled in - "AUTH_PROVIDER": "scp", - "ENABLE_AUTHZ": "false", - "RELATED_IMAGE_SPLUNK_ENTERPRISE": "splunk/splunk:9.4.1", - "RELATED_IMAGE_RAY_HEAD": "667741767953.dkr.ecr.us-west-2.amazonaws.com/ml-platform/ray/ray-head:build-5", - "RELATED_IMAGE_RAY_WORKER": "667741767953.dkr.ecr.us-west-2.amazonaws.com/ml-platform/ray/ray-worker-gpu:build-6", - "RELATED_IMAGE_WEAVIATE": "semitechnologies/weaviate:stable-v1.28-007846a", - "RELATED_IMAGE_SAIA_API": "667741767953.dkr.ecr.us-west-2.amazonaws.com/vivek/ml-platform/saia/saia-api:build-6", - "RELATED_IMAGE_POST_INSTALL_HOOK": "667741767953.dkr.ecr.us-west-2.amazonaws.com/vivek/ml-platform/saia/ai-helm-post-hook:0.0.5", - "CLUSTER_NAME": "sok-ml-platform", - "MODEL_VERSION" : "v0.3.14-36-g1549f5a", - "RAY_VERSION": "2.44.0", - "CA_CERT_PATH": "/Users/vivekr/Projects/splunk-ai-operator/etc/certs/tls.crt", - "INSTANCE_FILE": "/Users/vivekr/Projects/splunk-ai-operator/config/configs/instance.yaml", - "APPLICATION_FILE": "/Users/vivekr/Projects/splunk-ai-operator/config/configs/applications.yaml", - }, - }, - { - "name": "Debug test file", - "type": "go", - "request": "launch", - "mode": "test", - "program": "${workspaceFolder}/tests", - "envFile": "${workspaceFolder}/.env" - }, - { - "name": "Go: Test", - "type": "go", - "request": "launch", - "mode": "test", - "program": "${workspaceFolder}/tests", - "args": [ - "-parallel", - "4" - ] - } - ] -} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 0f6d11d..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "go.testTimeout": "1800m", - "go.testFlags": ["-v"], - //"go.testEnvFile": "${workspaceFolder}/test.env.aws", - -} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index f76fee4..0000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "version": "2.0.0", - "tasks": [ - { - "label": "Set Environment Variables", - "type": "shell", - "command": "./set_env.sh", - "problemMatcher": [], - "group": { - "kind": "build", - "isDefault": true - } - } - ] - } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..8e9cc27 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,121 @@ +# Changelog + +All notable changes to the Splunk AI Operator will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +### Added +- Comprehensive Helm chart testing with lint, template validation, and install/upgrade/uninstall tests +- GitHub issue templates (bug report, feature request) +- Pull request template with detailed checklist +- CONTRIBUTING.md with contributor guidelines +- CODE_OF_CONDUCT.md following Contributor Covenant standards +- SECURITY.md with security policy and vulnerability reporting process +- Comprehensive badge collection in README (25+ badges) +- Workflow audit documentation for GHCR migration + +### Changed +- README badges reorganized into logical categories +- Modular GitHub Actions workflows using `workflow_call` + +### Documentation +- Added deployment guides for EKS and k0s clusters +- Created comprehensive API documentation +- Added architecture diagrams +- Created troubleshooting guides + +## [0.1.0] - 2025-01-17 + +### Added +- Initial release of Splunk AI Operator +- Support for AIPlatform CRD +- Support for AIService CRD +- Integration with KubeRay for Ray cluster management +- Helm chart for operator deployment +- Helm chart for AI platform deployment +- Support for GPU and CPU workloads +- Integration with Splunk for logging and metrics +- Support for custom accelerator types +- Namespace isolation and multi-tenancy +- Automatic scaling configuration +- Volume mount support for models and data +- ConfigMap and Secret support for configuration +- Image pull secrets support for private registries +- Service mesh integration (optional) +- Prometheus metrics export +- OpenTelemetry tracing support + +### Cluster Setup +- EKS cluster setup script with full automation +- k0s cluster setup script for bare metal/VMs +- Support for Kubernetes 1.31-1.34 +- Automatic cluster-autoscaler installation +- GPU node support (NVIDIA, AMD) +- Spot instance support (EKS) +- Load balancer configuration +- Ingress controller setup +- Cert-manager integration +- Docker Hub authentication support +- Image pre-validation before deployment + +### CI/CD +- GitHub Actions workflows for build and test +- Unit test automation +- Code formatting checks +- Vulnerability scanning with Trivy +- Helm chart linting and testing +- Modular workflow design +- Automated release process + +### Documentation +- README with quick start guide +- Deployment guides for EKS and k0s +- API reference documentation +- Architecture overview +- Contributing guidelines +- Security policy +- Code of conduct + +## Release Types + +### Major Version (X.0.0) +- Breaking API changes +- Major feature additions +- Significant architectural changes + +### Minor Version (0.X.0) +- New features (backwards compatible) +- Deprecations +- Performance improvements +- Enhanced functionality + +### Patch Version (0.0.X) +- Bug fixes +- Security patches +- Documentation updates +- Minor improvements + +## Categories + +Changes are grouped into the following categories: + +- **Added**: New features +- **Changed**: Changes in existing functionality +- **Deprecated**: Soon-to-be removed features +- **Removed**: Removed features +- **Fixed**: Bug fixes +- **Security**: Security vulnerability fixes + +## Links + +- [GitHub Repository](https://github.com/splunk/splunk-ai-operator) +- [GitHub Releases](https://github.com/splunk/splunk-ai-operator/releases) +- [Documentation](https://github.com/splunk/splunk-ai-operator/tree/main/docs) +- [Issue Tracker](https://github.com/splunk/splunk-ai-operator/issues) + +--- + +**Note**: This project follows [Semantic Versioning](https://semver.org/). For information on how to contribute, see [CONTRIBUTING.md](CONTRIBUTING.md). diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..7c2e319 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,86 @@ +# Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our community include: + +- Demonstrating empathy and kindness toward other people +- Being respectful of differing opinions, viewpoints, and experiences +- Giving and gracefully accepting constructive feedback +- Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience +- Focusing on what is best not just for us as individuals, but for the overall community + +Examples of unacceptable behavior include: + +- The use of sexualized language or imagery, and sexual attention or advances of any kind +- Trolling, insulting or derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or email address, without their explicit permission +- Other conduct which could reasonably be considered inappropriate in a professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at **splunkai@cisco.com**. + +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series of actions. + +**Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 2.1, available at https://www.contributor-covenant.org/version/2/1/code_of_conduct.html. + +Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity). + +For answers to common questions about this code of conduct, see the FAQ at https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations. + +## Contact + +For questions or concerns about this Code of Conduct, please contact: + +- **Email**: splunkai@cisco.com +- **GitHub Issues**: [https://github.com/splunk/splunk-ai-operator/issues](https://github.com/splunk/splunk-ai-operator/issues) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..11f1097 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,400 @@ +# Contributing to Splunk AI Operator + +Thank you for your interest in contributing to the Splunk AI Operator! This document provides guidelines and instructions for contributing. + +## Table of Contents + +- [Code of Conduct](#code-of-conduct) +- [Getting Started](#getting-started) +- [How to Contribute](#how-to-contribute) +- [Development Setup](#development-setup) +- [Pull Request Process](#pull-request-process) +- [Coding Standards](#coding-standards) +- [Testing](#testing) +- [Documentation](#documentation) +- [Community](#community) + +## Code of Conduct + +This project adheres to a [Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please report unacceptable behavior to splunkai@cisco.com. + +## Getting Started + +1. **Fork the repository** on GitHub +2. **Clone your fork** locally: + ```bash + git clone https://github.com/YOUR_USERNAME/splunk-ai-operator.git + cd splunk-ai-operator + ``` +3. **Add upstream remote**: + ```bash + git remote add upstream https://github.com/splunk/splunk-ai-operator.git + ``` +4. **Create a branch** for your changes: + ```bash + git checkout -b feature/my-feature + ``` + +## How to Contribute + +### Reporting Bugs + +Before creating bug reports, please check existing issues to avoid duplicates. When creating a bug report, include: + +- **Clear title and description** +- **Steps to reproduce** the issue +- **Expected vs. actual behavior** +- **Environment details** (K8s version, operator version, cloud provider) +- **Logs and error messages** +- **Screenshots** if applicable + +Use the [bug report template](.github/ISSUE_TEMPLATE/bug_report.md) when creating issues. + +### Suggesting Enhancements + +Enhancement suggestions are tracked as GitHub issues. When creating an enhancement suggestion: + +- **Use a clear and descriptive title** +- **Provide a detailed description** of the proposed functionality +- **Explain why this enhancement would be useful** +- **List any similar features** in other projects + +Use the [feature request template](.github/ISSUE_TEMPLATE/feature_request.md) when creating suggestions. + +### Your First Code Contribution + +Unsure where to begin? Look for issues tagged with: + +- `good first issue` - Good for newcomers +- `help wanted` - Issues that need assistance +- `documentation` - Documentation improvements + +### Pull Requests + +1. **Ensure your PR addresses an existing issue** (or create one first) +2. **Follow the coding standards** outlined below +3. **Include tests** for new functionality +4. **Update documentation** as needed +5. **Keep PRs focused** - one feature or fix per PR +6. **Write clear commit messages** following conventional commits + +## Development Setup + +### Prerequisites + +- **Go**: 1.21 or higher +- **Docker**: For building container images +- **kubectl**: Kubernetes CLI tool +- **kind** or **minikube**: For local testing +- **make**: Build automation + +### Install Dependencies + +```bash +# Install Go dependencies +go mod download + +# Install development tools +make install-dev-tools +``` + +### Local Development + +```bash +# Run unit tests +make test + +# Run linters +make lint + +# Build the operator binary +make build + +# Build container image +make docker-build + +# Run locally (outside cluster) +make run +``` + +### Running Tests + +```bash +# Unit tests +make test + +# Integration tests +make test-integration + +# E2E tests (requires cluster) +make test-e2e + +# Test coverage +make coverage +``` + +## Pull Request Process + +### Before Submitting + +1. **Sync with upstream**: + ```bash + git fetch upstream + git rebase upstream/main + ``` + +2. **Run all tests**: + ```bash + make test + make lint + ``` + +3. **Update documentation**: + - Update README.md if adding features + - Add/update inline code comments + - Update API documentation + +4. **Update CHANGELOG.md** with your changes + +### Commit Message Format + +Follow [Conventional Commits](https://www.conventionalcommits.org/): + +``` +(): + + + +