Skip to content

Conversation

@manavgup
Copy link
Owner

8 Atomic Commits Created:

  1. e4648cb - chore: Update .gitignore
    - Added terraform patterns (.terraform/, *.tfstate, etc.)
    - Added helm charts directory pattern
    - Added session file patterns
  2. d9122fc - ci: Add security scanning workflow
    - Added comprehensive security scanning workflow
  3. 6dd6059 - docs: Add deployment documentation
    - MILVUS_OPERATOR_AUTOMATION.md
    - environment-variables.md
  4. 4ae7a46 - docs: Add architecture documentation
    - agent-mcp-architecture.md
    - mcp-context-forge-integration.md
  5. d6210ae - docs: Add security documentation
    - QUICK_START_REMEDIATION.md
    - REMEDIATION_SUMMARY.md
    - SECURITY_ALERT_ANALYSIS.md
    - SEQUENTIAL_REMEDIATION_PLAN.md
  6. 245d1d3 - feat: Add Ansible ROKS Milvus operator deployment playbook
    - deploy-roks-milvus-operator.yml
  7. 50bc050 - feat: Add Helm chart and templates
    - Chart.lock
    - 8 template YAML files (etcd, milvus, minio, mlflow, postgresql)
  8. 5ff8408 - feat: Add Terraform infrastructure code
    - IBM Cloud ROKS cluster configuration
    - Environment-specific configs (dev, IBM)
    - Infrastructure modules

Files Excluded (via .gitignore):

  • .terraform/ directories (148MB+ provider binaries)
  • *.tfstate files (infrastructure state)
  • tfplan files (execution plans)
  • deployment/helm/*/charts/ (generated dependencies)

manavgup and others added 7 commits November 25, 2025 19:45
- Add terraform patterns (.terraform/, *.tfstate, *.tfstate.backup, tfplan, *.tfplan)
- Add helm charts directory (deployment/helm/*/charts/)
- Add session file patterns (*_HANDOFF.md, *_IMPLEMENTATION_PLAN.md)

This prevents committing generated artifacts and temporary working documents.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Add comprehensive security scanning workflow for continuous security monitoring.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Add comprehensive deployment documentation including:
- Milvus operator automation guide
- Environment variables reference

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Add comprehensive architecture documentation including:
- Agent MCP architecture guide
- MCP context-forge integration guide

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Add comprehensive security documentation including:
- Quick start remediation guide
- Remediation summary
- Security alert analysis
- Sequential remediation plan

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Add comprehensive Ansible playbook for deploying Milvus operator on IBM ROKS (Red Hat OpenShift Kubernetes Service).

Includes:
- Automated operator installation
- Namespace management
- Custom resource deployment

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Add comprehensive Helm chart with templates for:
- Etcd StatefulSet
- Milvus operator deployment and custom resources
- MinIO StatefulSet
- MLFlow deployment
- PostgreSQL cluster and configuration

Includes Chart.lock for dependency management.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@github-actions
Copy link
Contributor

🚀 Development Environment Options

This repository supports Dev Containers for a consistent development environment.

Option 1: GitHub Codespaces (Recommended)

Create a cloud-based development environment:

  1. Click the green Code button above
  2. Select the Codespaces tab
  3. Click Create codespace on pr-branch
  4. Wait 2-3 minutes for environment setup
  5. Start coding with all tools pre-configured!

Option 2: VS Code Dev Containers (Local)

Use Dev Containers on your local machine:

  1. Install Docker Desktop
  2. Install VS Code
  3. Install the Dev Containers extension
  4. Clone this PR branch locally
  5. Open in VS Code and click "Reopen in Container" when prompted

Option 3: Traditional Local Setup

Set up the development environment manually:

# Clone the repository
git clone https://github.com/manavgup/rag_modulo.git
cd rag_modulo
git checkout pr-branch

# Initialize development environment
make dev-init
make dev-build
make dev-up
make dev-validate

Available Commands

Once in your development environment:

make help           # Show all available commands
make dev-validate   # Validate environment setup
make test-atomic    # Run atomic tests
make test-unit      # Run unit tests
make lint          # Run linting

Services Available

When running make dev-up:


This automated message helps reviewers quickly set up the development environment.

@@ -0,0 +1,3 @@
ibm_cloud_api_key = "5IPr_h4xttK2rBfGeoBD5LpFJIAwXno0NpVzPctFCw8q"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛑 Gitleaks has detected a secret with rule-id high-entropy-strings in commit 5ff8408d0cc353b6d227c61322e7f677c1454eea.
If this secret is a true positive, please rotate the secret ASAP.

If this secret is a false positive, you can add the fingerprint below to your .gitleaksignore file and commit the change to this branch.

echo 5ff8408d0cc353b6d227c61322e7f677c1454eea:deployment/terraform/environments/dev/terraform.tfvars:high-entropy-strings:1 >> .gitleaksignore

provider "registry.terraform.io/hashicorp/null" {
version = "3.2.4"
hashes = [
"h1:L5V05xwp/Gto1leRryuesxjMfgZwjb7oool4WS1UEFQ=",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛑 Gitleaks has detected a secret with rule-id high-entropy-strings in commit 5ff8408d0cc353b6d227c61322e7f677c1454eea.
If this secret is a true positive, please rotate the secret ASAP.

If this secret is a false positive, you can add the fingerprint below to your .gitleaksignore file and commit the change to this branch.

echo 5ff8408d0cc353b6d227c61322e7f677c1454eea:deployment/terraform/environments/dev/.terraform.lock.hcl:high-entropy-strings:7 >> .gitleaksignore

version = "1.85.0"
constraints = "~> 1.58"
hashes = [
"h1:kjHYHY8DxoUrfuwkXitnj1PyWfVM7rUm3D5kqglAJZc=",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛑 Gitleaks has detected a secret with rule-id high-entropy-strings in commit 5ff8408d0cc353b6d227c61322e7f677c1454eea.
If this secret is a true positive, please rotate the secret ASAP.

If this secret is a false positive, you can add the fingerprint below to your .gitleaksignore file and commit the change to this branch.

echo 5ff8408d0cc353b6d227c61322e7f677c1454eea:deployment/terraform/environments/dev/.terraform.lock.hcl:high-entropy-strings:27 >> .gitleaksignore

provider "registry.terraform.io/hashicorp/null" {
version = "3.2.4"
hashes = [
"h1:L5V05xwp/Gto1leRryuesxjMfgZwjb7oool4WS1UEFQ=",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛑 Gitleaks has detected a secret with rule-id high-entropy-strings in commit 5ff8408d0cc353b6d227c61322e7f677c1454eea.
If this secret is a true positive, please rotate the secret ASAP.

If this secret is a false positive, you can add the fingerprint below to your .gitleaksignore file and commit the change to this branch.

echo 5ff8408d0cc353b6d227c61322e7f677c1454eea:deployment/terraform/roks-deployment/.terraform.lock.hcl:high-entropy-strings:7 >> .gitleaksignore

version = "1.85.0"
constraints = "~> 1.0"
hashes = [
"h1:kjHYHY8DxoUrfuwkXitnj1PyWfVM7rUm3D5kqglAJZc=",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛑 Gitleaks has detected a secret with rule-id high-entropy-strings in commit 5ff8408d0cc353b6d227c61322e7f677c1454eea.
If this secret is a true positive, please rotate the secret ASAP.

If this secret is a false positive, you can add the fingerprint below to your .gitleaksignore file and commit the change to this branch.

echo 5ff8408d0cc353b6d227c61322e7f677c1454eea:deployment/terraform/roks-deployment/.terraform.lock.hcl:high-entropy-strings:27 >> .gitleaksignore

provider "registry.terraform.io/hashicorp/null" {
version = "3.2.4"
hashes = [
"h1:L5V05xwp/Gto1leRryuesxjMfgZwjb7oool4WS1UEFQ=",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛑 Gitleaks has detected a secret with rule-id high-entropy-strings in commit 5ff8408d0cc353b6d227c61322e7f677c1454eea.
If this secret is a true positive, please rotate the secret ASAP.

If this secret is a false positive, you can add the fingerprint below to your .gitleaksignore file and commit the change to this branch.

echo 5ff8408d0cc353b6d227c61322e7f677c1454eea:deployment/terraform/modules/ibm-cloud/roks-cluster/.terraform.lock.hcl:high-entropy-strings:7 >> .gitleaksignore

version = "1.85.0"
constraints = "~> 1.0"
hashes = [
"h1:kjHYHY8DxoUrfuwkXitnj1PyWfVM7rUm3D5kqglAJZc=",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛑 Gitleaks has detected a secret with rule-id high-entropy-strings in commit 5ff8408d0cc353b6d227c61322e7f677c1454eea.
If this secret is a true positive, please rotate the secret ASAP.

If this secret is a false positive, you can add the fingerprint below to your .gitleaksignore file and commit the change to this branch.

echo 5ff8408d0cc353b6d227c61322e7f677c1454eea:deployment/terraform/modules/ibm-cloud/roks-cluster/.terraform.lock.hcl:high-entropy-strings:27 >> .gitleaksignore

@github-advanced-security
Copy link

This pull request sets up GitHub code scanning for this repository. Once the scans have completed and the checks have passed, the analysis results for this pull request branch will appear on this overview. Once you merge this pull request, the 'Security' tab will show more code scanning analysis results (for example, for the default branch). Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results. For more information about GitHub code scanning, check out the documentation.

@github-actions
Copy link
Contributor

Pull Request Review - PR #678

Summary

This PR adds significant infrastructure and deployment code (~8,244 additions) including Terraform modules, Helm charts, Ansible playbooks, security workflows, and extensive documentation. While the additions are comprehensive, there are several critical issues that must be addressed before merging.

🚨 Critical Issues

1. Duplicate Security Workflow (Naming Conflict)

Severity: HIGH - Will cause CI/CD failure

  • File: .github/workflows/security-scan.yml
  • Issue: This workflow has the exact same name (name: Security Scan) as the existing .github/workflows/02-security.yml
  • Impact: GitHub Actions will have naming conflicts, making it unclear which workflow runs when
  • Location: Lines 1-209 in security-scan.yml

Existing workflow (02-security.yml):

name: Security Scan  # ← DUPLICATE NAME
on:
  pull_request:
    branches: [main]
  push:
    branches: [main]
jobs:
  gitleaks: ...
  trufflehog: ...

New workflow (security-scan.yml):

name: Security Scan  # ← DUPLICATE NAME
on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main, develop]
jobs:
  python-security: ...
  node-security: ...
  docker-security: ...

Recommendations:

  1. Rename the new workflow to name: Comprehensive Security Audit or name: Multi-Layer Security Scan
  2. Consolidate both workflows into one comprehensive security workflow
  3. Remove duplication - both workflows scan Docker images with Trivy and run Gitleaks
  4. Follow the existing naming convention: 08-comprehensive-security.yml

2. Hardcoded Absolute Path in Ansible Playbook

Severity: HIGH - Will fail on any other system

  • File: deployment/ansible/playbooks/deploy-roks-milvus-operator.yml
  • Line: 242
  • Issue: Hardcoded absolute path that only works on your local machine
args:
  chdir: /Users/mg/mg-work/manav/work/ai-experiments/rag_modulo  # ← HARDCODED PATH

Impact: Playbook will fail immediately when run by anyone else or in CI/CD
Fix: Use relative path or environment variable

args:
  chdir: "{{ playbook_dir }}/../../.."  # Relative to playbook location

3. Missing Helm Chart values.yaml

Severity: HIGH - Helm chart is incomplete

  • Files Added: Multiple Helm templates (etcd-statefulset.yaml, milvus-cr.yaml, minio-statefulset.yaml, etc.)
  • Missing: deployment/helm/rag-modulo/values.yaml and Chart.yaml
  • Impact: Templates reference .Values.* that don't exist, chart cannot be installed
  • Example Issues:
    • milvus-cr.yaml:1 - {{- if .Values.milvus.enabled }} (undefined)
    • minio-statefulset.yaml:14 - {{ .Values.minio.auth.rootUser }} (undefined)
    • etcd-statefulset.yaml:25 - {{ .Values.etcd.image.repository }} (undefined)

Required Files:

  • deployment/helm/rag-modulo/Chart.yaml (metadata, version, dependencies)
  • deployment/helm/rag-modulo/values.yaml (default configuration values)
  • deployment/helm/rag-modulo/templates/_helpers.tpl (template functions referenced like {{ include "rag-modulo.fullname" . }})

4. Terraform Lock Files Should Not Be Committed

Severity: MEDIUM - Against best practices

  • Files:
    • deployment/terraform/environments/dev/.terraform.lock.hcl
    • deployment/terraform/modules/ibm-cloud/roks-cluster/.terraform.lock.hcl
    • deployment/terraform/roks-deployment/.terraform.lock.hcl
  • Issue: .terraform.lock.hcl files are platform-specific and should generally not be committed to avoid cross-platform issues
  • Current .gitignore: Already has *.tfstate but missing .terraform.lock.hcl

Recommendation:

# Terraform
.terraform/
*.tfstate
*.tfstate.backup
tfplan
*.tfplan
*.terraform.lock.hcl  #  ADD THIS

Note: Some teams commit lock files for consistency, but this should be a deliberate decision documented in the project's Terraform practices.

5. Security: Overly Permissive Network Rules

Severity: MEDIUM - Security risk

  • File: deployment/terraform/modules/ibm-cloud/roks-cluster/main.tf
  • Lines: 68-95
  • Issue: Security group rules allow unrestricted inbound traffic from the internet (0.0.0.0/0)
# Lines 77-85: HTTPS from ANYWHERE
resource "ibm_is_security_group_rule" "cluster_sg_rule_inbound_https" {
  direction = "inbound"
  remote    = "0.0.0.0/0"  # ← TOO PERMISSIVE
  tcp {
    port_min = 443
    port_max = 443
  }
}

# Lines 87-95: HTTP from ANYWHERE  
resource "ibm_is_security_group_rule" "cluster_sg_rule_inbound_http" {
  remote    = "0.0.0.0/0"  # ← TOO PERMISSIVE
  tcp {
    port_min = 80
    port_max = 80
  }
}

Recommendations:

  1. Restrict by IP range: Only allow known corporate/VPN IP ranges
  2. Use variables: Make CIDR blocks configurable
  3. Disable HTTP: Production clusters should not allow unencrypted HTTP (port 80)
  4. Add comments: Document why rules are needed

Example hardening:

variable "allowed_cidr_blocks" {
  description = "CIDR blocks allowed to access the cluster"
  type        = list(string)
  default     = []  # Must be explicitly set
}

resource "ibm_is_security_group_rule" "cluster_sg_rule_inbound_https" {
  for_each  = toset(var.allowed_cidr_blocks)
  direction = "inbound"
  remote    = each.value
  tcp {
    port_min = 443
    port_max = 443
  }
}

⚠️ Major Issues

6. CI Workflow Duplication and Inefficiency

Severity: MEDIUM

The new security-scan.yml workflow duplicates functionality already present in:

  • 02-security.yml - Gitleaks, TruffleHog
  • 03-build-secure.yml - Docker builds with Trivy scans
  • 06-weekly-security-audit.yml - Comprehensive security auditing

Problems:

  1. Runs too frequently: Builds Docker images on every push/PR, even for doc-only changes
  2. No path filtering: Missing optimization from CLAUDE.md requirements
  3. Resource waste: Duplicate Trivy scans (already in 03-build-secure.yml)
  4. continue-on-error: true: Security findings don't fail the build (lines 39, 45, 52, 87)

Impact per CLAUDE.md:

"CI/CD Pipeline has been optimized for fast PR feedback (~2-3 min)"
"Smart Path Filtering: Docker builds only when code/dependencies change"

This workflow violates the project's optimized CI/CD strategy (Issue #349).

Recommendations:

  1. Add path filters:
on:
  push:
    branches: [main, develop]
    paths:
      - 'backend/**'
      - 'frontend/**'
      - '**/Dockerfile*'
      - 'poetry.lock'
      - 'package-lock.json'
  1. Remove continue-on-error or add proper failure thresholds
  2. Consolidate with existing security workflows

7. Documentation Completeness

Severity: MEDIUM

Large documentation files were added but lack proper integration:

Added Docs (3,438 lines):

  • docs/deployment/MILVUS_OPERATOR_AUTOMATION.md (408 lines)
  • docs/deployment/environment-variables.md (410 lines)
  • docs/design/agent-mcp-architecture.md (946 lines)
  • docs/design/mcp-context-forge-integration.md (1,129 lines)
  • docs/security/QUICK_START_REMEDIATION.md (331 lines)
  • docs/security/REMEDIATION_SUMMARY.md (382 lines)
  • docs/security/SECURITY_ALERT_ANALYSIS.md (589 lines)
  • docs/security/SEQUENTIAL_REMEDIATION_PLAN.md (2,169 lines)

Missing:

  • No updates to main README.md linking to new deployment docs
  • No updates to docs/deployment/index.md (if it exists)
  • No updates to CLAUDE.md about new Terraform/Ansible/Helm deployment options
  • Security docs seem like analysis artifacts rather than user-facing guides

Questions:

  • Are the security docs (QUICK_START_REMEDIATION.md, SECURITY_ALERT_ANALYSIS.md, etc.) meant to be committed or are they working documents?
  • Should they be in .gitignore like the new patterns (*_HANDOFF.md, *_IMPLEMENTATION_PLAN.md)?

8. Missing Terraform Module Documentation

Severity: MEDIUM

  • File: deployment/terraform/modules/ibm-cloud/roks-cluster/
  • Missing: README.md documenting module usage, inputs, outputs, examples
  • Issue: variables.tf has 165 lines but no usage documentation

Best Practice: Terraform modules should have:

deployment/terraform/modules/ibm-cloud/roks-cluster/
├── README.md           # ← MISSING (usage, examples, prerequisites)
├── main.tf
├── variables.tf
├── outputs.tf
└── versions.tf         # ← MISSING (provider version constraints)

💡 Minor Issues & Improvements

9. Incomplete .gitignore Updates

File: .gitignore

Good additions:
✅ Terraform patterns (.terraform/, *.tfstate, etc.)
✅ Helm charts directory
✅ Session file patterns

Missing patterns:

# Ansible
*.retry
.ansible/

# Terraform (additional)
*.terraform.lock.hcl
.terraform.tfstate.lock.info

# Helm (additional)  
deployment/helm/*/Chart.lock  # Lock file in PR but not .gitignore

# IDE
.vscode/
.idea/
*.swp
*.swo

10. Ansible Playbook Best Practices

File: deployment/ansible/playbooks/deploy-roks-milvus-operator.yml

Good: Comprehensive playbook with proper structure, error handling, and summary output

Improvements:

  1. Line 242: Hardcoded path (already noted as critical)
  2. Line 164: Uses local-exec to configure kubectl - should use Ansible k8s module
  3. No ansible.cfg: Missing Ansible configuration file
  4. No inventory file: Should include example inventory for dev/staging/prod
  5. No requirements.yml: Should specify required Ansible collections

Example:

# deployment/ansible/requirements.yml
collections:
  - name: kubernetes.core
    version: ">=2.3.0"
  - name: community.general

11. Helm Templates - Resource Limits

Files: All Helm templates

Good: Resource requests/limits defined
Issue: Values are reasonable for dev but need documentation for production sizing

Example (milvus-cr.yaml:33-39):

standalone:
  replicas: 1  # OK for dev
  resources:
    limits:
      cpu: "1"        # Too small for production
      memory: 2Gi     # Too small for production

Recommendation: Add production values override example in missing values.yaml

12. Terraform Outputs Documentation

File: deployment/terraform/modules/ibm-cloud/roks-cluster/outputs.tf

Good: Comprehensive outputs (72 lines)
Improvement: Add descriptions to outputs for better UX

Example:

output "cluster_id" {
  description = "The unique identifier of the ROKS cluster"
  value       = ibm_container_vpc_cluster.roks_cluster.id
}

output "cluster_ingress_hostname" {
  description = "The hostname of the cluster ingress controller"
  value       = ibm_container_vpc_cluster.roks_cluster.ingress_hostname
  sensitive   = false
}

13. Chart.lock Should Not Be Committed

File: deployment/helm/rag-modulo/Chart.lock

Issue: Similar to Terraform lock files, Chart.lock is typically generated and may cause issues across environments

Standard Practice: Add to .gitignore:

# Helm
deployment/helm/*/charts/     #  Already added
deployment/helm/*/Chart.lock  #  ADD THIS

However, some teams commit Chart.lock for reproducibility. Make this a deliberate decision.

14. Workflow Comments

File: .github/workflows/security-scan.yml:209

# Made with Bob

Minor: Personal comment should be removed. Use proper attribution in commit messages instead.


✅ Positive Aspects

  1. Comprehensive Infrastructure Code: Well-structured Terraform modules with proper resource organization
  2. Production-Ready Ansible: Playbook includes proper error handling, retries, and user feedback
  3. Security Conscious: Multiple layers of security scanning (Python, Node.js, Docker, secrets)
  4. Proper Separation: Clear separation between dev/staging/prod environments in Terraform
  5. Good Helm Structure: Templates follow Kubernetes best practices with proper labels and selectors
  6. Documentation Volume: Extensive documentation added (though needs integration)
  7. Proper Namespacing: Kubernetes resources properly namespaced and labeled

📋 Required Actions Before Merge

Must Fix (Blockers):

  1. Rename duplicate security workflow (security-scan.yml)
  2. Fix hardcoded path in Ansible playbook (line 242)
  3. Add missing Helm files (Chart.yaml, values.yaml, _helpers.tpl)
  4. Remove or justify Terraform/Helm lock files
  5. Harden security group rules (restrict 0.0.0.0/0)

Should Fix:

  1. ⚠️ Add path filtering to security workflow
  2. ⚠️ Remove continue-on-error from security scans or document why failures are acceptable
  3. ⚠️ Add Terraform module README with usage examples
  4. ⚠️ Clarify security docs status (user docs vs. analysis artifacts)
  5. ⚠️ Update main documentation to reference new deployment options

Nice to Have:

  1. 💡 Complete .gitignore with Ansible and IDE patterns
  2. 💡 Add Ansible requirements.yml and example inventory
  3. 💡 Add Terraform versions.tf to module
  4. 💡 Document production resource sizing for Helm charts
  5. 💡 Remove personal comments from workflow files

🧪 Testing Recommendations

Before merging, please verify:

  1. Helm Chart:

    helm lint deployment/helm/rag-modulo/
    helm template rag-modulo deployment/helm/rag-modulo/ --debug
  2. Terraform Module:

    cd deployment/terraform/modules/ibm-cloud/roks-cluster/
    terraform init
    terraform validate
    terraform plan
  3. Ansible Playbook:

    ansible-playbook deployment/ansible/playbooks/deploy-roks-milvus-operator.yml --syntax-check
    ansible-lint deployment/ansible/playbooks/deploy-roks-milvus-operator.yml
  4. Workflow Syntax:

    actionlint .github/workflows/security-scan.yml

📊 PR Statistics

  • Files Changed: 29
  • Lines Added: 8,244
  • Lines Deleted: 0
  • Commits: 8 atomic commits (good!)
  • Documentation: ~3,438 lines
  • Infrastructure Code: ~1,200 lines (Terraform + Ansible + Helm)
  • CI/CD: 209 lines (workflow)

🎯 Conclusion

This PR adds valuable infrastructure-as-code to enable RAG Modulo deployment on IBM ROKS with Milvus Operator. However, several critical issues must be addressed before merging:

  1. The duplicate workflow naming will cause immediate CI/CD conflicts
  2. The hardcoded path will break the Ansible playbook for other users
  3. Missing Helm chart files make the deployment incomplete
  4. Security hardening needed for production use

Recommendation: 🔴 Request Changes - Address the 5 must-fix blockers, then re-review.

Once these issues are resolved, this will be a strong addition to the project's deployment capabilities. The code structure is solid and follows infrastructure best practices.


Reviewed with reference to: CLAUDE.md, existing CI/CD workflows, and infrastructure best practices.

Add comprehensive Terraform modules and configurations for:
- IBM Cloud ROKS cluster provisioning
- Environment-specific configurations (dev, IBM)
- Infrastructure module for cluster management

Includes:
- Terraform lock files for dependency management
- Example tfvars for configuration templates
- Main, variables, and outputs definitions

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
provider "registry.terraform.io/hashicorp/null" {
version = "3.2.4"
hashes = [
"h1:L5V05xwp/Gto1leRryuesxjMfgZwjb7oool4WS1UEFQ=",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛑 Gitleaks has detected a secret with rule-id high-entropy-strings in commit fd20c62.
If this secret is a true positive, please rotate the secret ASAP.

If this secret is a false positive, you can add the fingerprint below to your .gitleaksignore file and commit the change to this branch.

echo fd20c62e24eea88696541d8e23a79428b2a8bcfa:deployment/terraform/modules/ibm-cloud/roks-cluster/.terraform.lock.hcl:high-entropy-strings:7 >> .gitleaksignore

version = "1.85.0"
constraints = "~> 1.0"
hashes = [
"h1:kjHYHY8DxoUrfuwkXitnj1PyWfVM7rUm3D5kqglAJZc=",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛑 Gitleaks has detected a secret with rule-id high-entropy-strings in commit fd20c62.
If this secret is a true positive, please rotate the secret ASAP.

If this secret is a false positive, you can add the fingerprint below to your .gitleaksignore file and commit the change to this branch.

echo fd20c62e24eea88696541d8e23a79428b2a8bcfa:deployment/terraform/modules/ibm-cloud/roks-cluster/.terraform.lock.hcl:high-entropy-strings:27 >> .gitleaksignore

provider "registry.terraform.io/hashicorp/null" {
version = "3.2.4"
hashes = [
"h1:L5V05xwp/Gto1leRryuesxjMfgZwjb7oool4WS1UEFQ=",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛑 Gitleaks has detected a secret with rule-id high-entropy-strings in commit fd20c62.
If this secret is a true positive, please rotate the secret ASAP.

If this secret is a false positive, you can add the fingerprint below to your .gitleaksignore file and commit the change to this branch.

echo fd20c62e24eea88696541d8e23a79428b2a8bcfa:deployment/terraform/roks-deployment/.terraform.lock.hcl:high-entropy-strings:7 >> .gitleaksignore

version = "1.85.0"
constraints = "~> 1.0"
hashes = [
"h1:kjHYHY8DxoUrfuwkXitnj1PyWfVM7rUm3D5kqglAJZc=",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛑 Gitleaks has detected a secret with rule-id high-entropy-strings in commit fd20c62.
If this secret is a true positive, please rotate the secret ASAP.

If this secret is a false positive, you can add the fingerprint below to your .gitleaksignore file and commit the change to this branch.

echo fd20c62e24eea88696541d8e23a79428b2a8bcfa:deployment/terraform/roks-deployment/.terraform.lock.hcl:high-entropy-strings:27 >> .gitleaksignore

provider "registry.terraform.io/hashicorp/null" {
version = "3.2.4"
hashes = [
"h1:L5V05xwp/Gto1leRryuesxjMfgZwjb7oool4WS1UEFQ=",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛑 Gitleaks has detected a secret with rule-id high-entropy-strings in commit fd20c62.
If this secret is a true positive, please rotate the secret ASAP.

If this secret is a false positive, you can add the fingerprint below to your .gitleaksignore file and commit the change to this branch.

echo fd20c62e24eea88696541d8e23a79428b2a8bcfa:deployment/terraform/environments/dev/.terraform.lock.hcl:high-entropy-strings:7 >> .gitleaksignore

version = "1.85.0"
constraints = "~> 1.58"
hashes = [
"h1:kjHYHY8DxoUrfuwkXitnj1PyWfVM7rUm3D5kqglAJZc=",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛑 Gitleaks has detected a secret with rule-id high-entropy-strings in commit fd20c62.
If this secret is a true positive, please rotate the secret ASAP.

If this secret is a false positive, you can add the fingerprint below to your .gitleaksignore file and commit the change to this branch.

echo fd20c62e24eea88696541d8e23a79428b2a8bcfa:deployment/terraform/environments/dev/.terraform.lock.hcl:high-entropy-strings:27 >> .gitleaksignore

@github-actions
Copy link
Contributor

Pull Request Review: Infrastructure and Deployment Enhancements

Summary: This PR adds substantial infrastructure-as-code, deployment automation, and security scanning capabilities to RAG Modulo. Overall, this is a positive contribution that significantly improves the project's production-readiness. However, there are several critical issues that must be addressed before merging.


🔴 Critical Issues

1. Missing Helm Chart Dependencies

  • File: deployment/helm/rag-modulo/Chart.yaml
  • Issue: The Chart.yaml exists but does not declare the Milvus dependency referenced in Chart.lock
  • Impact: Helm will fail to install the chart
  • Fix Required: Add this to Chart.yaml:
dependencies:
  - name: milvus
    version: 4.2.14
    repository: https://zilliztech.github.io/milvus-helm/
    condition: milvus.enabled

2. Missing values.yaml File

  • Files: All Helm templates reference .Values.* extensively
  • Issue: The PR includes templates but no values.yaml file to define default values
  • Impact: Helm chart is completely non-functional without this file
  • Fix Required: Create deployment/helm/rag-modulo/values.yaml with all necessary default values for:
    • milvus.*
    • etcd.*
    • minio.*
    • postgresql.*
    • mlflow.*
    • backend.*
    • frontend.*
    • image.*

3. Security Workflow Issues

  • File: .github/workflows/security-scan.yml

  • Issues:

    1. Line 123: Backend Dockerfile path is incorrect - should be backend/Dockerfile (relative to repo root)
    2. Line 32: Installing dependencies with --no-root may cause Poetry to skip critical packages
    3. All security scans use continue-on-error: true - This means security failures won't block merges
  • Fix Required:

# Line 123 - Fix Docker build context
docker build -t rag-modulo-backend:test -f backend/Dockerfile .

# Line 32 - Remove --no-root flag
poetry install --with dev,test

# Lines 39, 45, 52 - Remove continue-on-error for critical security checks
# Only keep it for informational scans

4. Hardcoded Absolute Path in Ansible Playbook

  • File: deployment/ansible/playbooks/deploy-roks-milvus-operator.yml:241
  • Issue: chdir: /Users/mg/mg-work/manav/work/ai-experiments/rag_modulo is a hardcoded absolute path specific to one developer's machine
  • Impact: Playbook will fail for all other users
  • Fix Required: Use relative path or remove the chdir entirely (it's already running from repo root)

⚠️ Important Security Concerns

5. Overly Permissive Security Group Rules

  • File: deployment/terraform/modules/ibm-cloud/roks-cluster/main.tf:62-95
  • Issue: Security group allows inbound traffic from 0.0.0.0/0 (entire internet) on ports 80, 443, and ICMP
  • Risk: Production clusters should use more restrictive ingress rules
  • Recommendation:
    • Add variables for allowed CIDR blocks
    • Default to private/VPC-only access
    • Document why public access is needed (if it is)

6. No Encryption Configuration

  • Files: Milvus, MinIO, PostgreSQL templates
  • Issue: No encryption-at-rest or encryption-in-transit configuration
  • Impact: Non-compliant for most enterprise security policies
  • Recommendation:
    • PostgreSQL: Add SSL/TLS configuration
    • MinIO: Enable encryption-at-rest
    • Milvus: Configure TLS for gRPC communication

7. Secret Management Anti-Pattern

  • File: deployment/helm/rag-modulo/templates/minio-statefulset.yaml:15
  • Issue: Default password generation using randAlphaNum 32 in Helm
  • Risk: Password changes on every helm upgrade, breaking existing deployments
  • Fix Required: Use lookup function to preserve existing secrets:
rootPassword: {{ .Values.minio.auth.rootPassword | default (lookup "v1" "Secret" .Release.Namespace "minio-credentials").data.rootPassword | b64dec | default (randAlphaNum 32) }}

🟡 Code Quality Issues

8. Terraform: Missing null_resource Provider

  • File: deployment/terraform/modules/ibm-cloud/roks-cluster/main.tf:160-170
  • Issue: Uses null_resource but doesn't declare null provider in required_providers
  • Fix: Add to terraform block:
null = {
  source  = "hashicorp/null"
  version = "~> 3.0"
}

9. Terraform: Insecure local-exec Provisioner

  • File: deployment/terraform/modules/ibm-cloud/roks-cluster/main.tf:163-165
  • Issue: local-exec provisioner runs ibmcloud commands that modify local kubectl config
  • Risk: Side effects on developer machines, not idempotent, hard to debug
  • Better Approach: Use Terraform's kubernetes provider with data sources

10. Ansible: No Error Handling for Critical Operations

  • File: deployment/ansible/playbooks/deploy-roks-milvus-operator.yml
  • Issues:
    • Many tasks use failed_when: false which masks real errors
    • No validation of prerequisites (oc login status, credentials)
    • No rollback strategy if deployment fails mid-way
  • Recommendation: Add proper error handling and validation tasks

11. Docker Build Context Issues

  • File: .github/workflows/security-scan.yml:123, 135
  • Issue: Building from root context (.) but Dockerfiles expect to be in their subdirectories
  • Impact: May work but violates CLAUDE.md guidance about Docker builds
  • Clarification Needed: Verify Dockerfiles are designed for root context builds

🟢 Positive Aspects

✅ Comprehensive Security Scanning

  • Multi-layered approach: Trivy, Gitleaks, pip-audit, Safety, Bandit
  • Proper SARIF upload to GitHub Security tab
  • Scheduled weekly scans for continuous monitoring

✅ Production-Ready Terraform Module

  • Well-structured IBM Cloud ROKS module
  • Multi-zone deployment for high availability
  • Proper use of data sources and dynamic blocks
  • Good variable design with sensible defaults

✅ Excellent Documentation

  • Comprehensive deployment guides
  • Clear architecture documentation
  • Security remediation plans
  • Environment variable documentation

✅ Proper .gitignore Updates

  • Correctly excludes Terraform state files
  • Excludes Helm chart dependencies
  • Excludes temporary documentation files
  • Follows project conventions

✅ Milvus Operator Integration

  • Uses custom resource definitions (CRDs) for declarative management
  • Proper SCC (Security Context Constraints) handling for OpenShift
  • Supports both standalone and cluster modes

📋 Additional Recommendations

12. Helm Chart Testing

Before merging, verify:

# Test Helm chart linting
helm lint deployment/helm/rag-modulo

# Test dry-run install
helm install --dry-run --debug rag-modulo deployment/helm/rag-modulo

# Test template rendering
helm template rag-modulo deployment/helm/rag-modulo

13. GitHub Actions Optimization

According to CLAUDE.md, the project uses optimized CI/CD workflows:

  • This new security-scan.yml should be integrated with existing workflows
  • Consider path filtering to avoid running on documentation-only changes
  • Add concurrency control to cancel outdated runs

14. Documentation Updates Needed

  • Update CLAUDE.md to document new deployment options (Ansible, Terraform, Helm)
  • Add Helm chart usage to "Running the Application" section
  • Document required IBM Cloud permissions for Terraform
  • Add troubleshooting guide for OpenShift SCC issues

15. Resource Limits Review

PostgreSQL StatefulSet (line 52-58):

resources:
  requests:
    memory: "512Mi"
    cpu: "500m"
  limits:
    memory: "2Gi"
    cpu: "2000m"
  • Issue: 4x memory limit vs request can cause OOM kills
  • Recommendation: Closer ratio (e.g., 2x max) for stability

🎯 Verdict

Recommendation: REQUEST CHANGES

This PR adds significant value but cannot be merged in its current state due to:

  1. ❌ Missing Helm values.yaml (chart is non-functional)
  2. ❌ Broken Helm Chart.yaml dependencies
  3. ❌ Hardcoded developer path in Ansible playbook
  4. ⚠️ Security scan workflow won't block on failures

Required Actions Before Merge:

  1. Add deployment/helm/rag-modulo/values.yaml with all required values
  2. Fix Chart.yaml dependencies declaration
  3. Remove hardcoded path from Ansible playbook (line 241)
  4. Fix security workflow to actually fail on critical issues
  5. Fix Dockerfile paths in security-scan.yml
  6. Add null provider to Terraform module
  7. Implement proper secret management in Helm templates

Recommended Actions (Can be follow-up PRs):

  • Tighten security group rules to use CIDR variables
  • Add encryption configuration for all data stores
  • Improve error handling in Ansible playbook
  • Add Helm chart tests
  • Update CLAUDE.md with new deployment documentation

📊 Statistics

  • Files Changed: 29 files
  • Additions: 8,250 lines
  • Deletions: 0 lines
  • New Workflows: 1 (security-scan.yml)
  • New Helm Templates: 8 templates
  • Documentation: 8 new docs (2,075 lines)

Thank you for this substantial contribution! Once the critical issues are addressed, this will be a great addition to the project. 🚀

@github-actions
Copy link
Contributor

Code Review Summary

Thank you for this comprehensive infrastructure-as-code PR! This adds significant deployment capabilities with Terraform, Helm, and Ansible. Here's my detailed review:

✅ Strengths

1. Excellent Organization & Structure

  • Well-organized atomic commits (8 commits, each with clear purpose)
  • Clean separation of concerns: Terraform for infrastructure, Helm for Kubernetes resources, Ansible for orchestration
  • Comprehensive documentation added alongside code

2. Security Best Practices

  • ✅ No hardcoded secrets found (all use {{.Values}} placeholders, environment variables, or .tfvars.example files)
  • ✅ Good use of Kubernetes secrets and secret references
  • ✅ Proper .gitignore updates to prevent committing sensitive files (*.tfstate, *.tfvars, .terraform/)
  • ✅ Test files correctly use # pragma: allowlist secret for test credentials

3. Production-Ready Infrastructure

  • Multi-zone HA configuration for ROKS cluster (3 zones, 2 workers per zone)
  • Proper resource sizing recommendations (bx2.8x32 with 8 vCPUs, 32GB RAM)
  • CloudNativePG for PostgreSQL with 3 replicas
  • Proper health checks and readiness probes throughout

4. Good Documentation

  • 4,464 lines of documentation added
  • Clear usage examples and prerequisites in Ansible playbook
  • Comprehensive architecture and security docs

🔧 Issues & Recommendations

1. Critical: Hardcoded Paths in Ansible ⚠️

Location: deployment/ansible/playbooks/deploy-roks-milvus-operator.yml:240

args:
  chdir: /Users/mg/mg-work/manav/work/ai-experiments/rag_modulo

Issue: This is a hardcoded absolute path to a developer's local machine. This will fail for any other user or CI/CD environment.

Fix:

# Remove the args block entirely, or use:
args:
  chdir: "{{ playbook_dir }}/../.."  # Relative to playbook location

2. Security: Overly Permissive Security Group Rules

Location: deployment/terraform/modules/ibm-cloud/roks-cluster/main.tf:62-75

remote = "0.0.0.0/0"  # Lines 65, 71, 79

Issue: Allows inbound traffic from any IP address. This is too permissive for production.

Recommendation:

  • Use VPC CIDR blocks or specific IP ranges instead of 0.0.0.0/0
  • Add variables for allowed CIDR blocks:
variable "allowed_cidr_blocks" {
  description = "CIDR blocks allowed to access the cluster"
  type        = list(string)
  default     = []  # Force users to explicitly set this
}

resource "ibm_is_security_group_rule" "cluster_sg_rule_inbound_https" {
  remote = length(var.allowed_cidr_blocks) > 0 ? var.allowed_cidr_blocks[0] : "0.0.0.0/0"
}

3. Missing Terraform Backend Configuration Validation

Location: deployment/terraform/backend.tf:11

key = "ibm/environments/terraform.tfstate"

Issue: The backend configuration expects AWS S3, but the code targets IBM Cloud. This could cause confusion.

Recommendation:

  • Add a comment explaining why S3 is used (or use IBM Cloud Object Storage instead)
  • Document the backend setup in docs/deployment/
  • Consider adding backend.tf.example since backend configs can't use variables

4. Helm: Default Password Generation May Not Persist

Location: Multiple files (e.g., minio-statefulset.yaml:15, postgresql-secret.yaml:15)

rootPassword: {{ .Values.minio.auth.rootPassword | default (randAlphaNum 32) }}

Issue: randAlphaNum generates a new password on every Helm upgrade, which will break existing deployments.

Fix:

# Use lookup to retrieve existing secret if it exists
{{- if not .Values.minio.auth.rootPassword }}
{{- $existingSecret := lookup "v1" "Secret" .Release.Namespace "minio-credentials" }}
{{- if $existingSecret }}
rootPassword: {{ $existingSecret.data.rootPassword | b64dec }}
{{- else }}
rootPassword: {{ randAlphaNum 32 }}
{{- end }}
{{- else }}
rootPassword: {{ .Values.minio.auth.rootPassword }}
{{- end }}

Or better yet, require users to set passwords explicitly in production.

5. Terraform: Missing Required Providers Lock Files

Files Added: 3 .terraform.lock.hcl files

Issue: Lock files are committed, which is correct for modules/environments. However, ensure they're generated on the target platform:

Action Needed:

# Regenerate lock files for multiple platforms (CI needs this)
cd deployment/terraform/modules/ibm-cloud/roks-cluster
terraform providers lock -platform=linux_amd64 -platform=darwin_amd64 -platform=darwin_arm64

6. Documentation: Environment Variables Doc Duplicates .env.example

File: docs/deployment/environment-variables.md (410 lines)

Issue: This creates a documentation debt - two places to maintain the same information.

Recommendation:

  • Reference .env.example as the source of truth
  • Keep the doc focused on explanations and examples, not listing all vars
  • Or generate the doc from .env.example using a script

7. Ansible: Missing Idempotency Check

Location: Multiple command: tasks in Ansible playbook

Issue: Using command: instead of shell: or native modules reduces idempotency. The playbook will show "changed" on every run even if nothing changed.

Recommendation:

# Instead of:
- name: Install Milvus Operator via Helm
  command: helm upgrade --install ...
  changed_when: true

# Use:
- name: Install Milvus Operator via Helm
  command: helm upgrade --install ...
  register: helm_install
  changed_when: '"has been upgraded" in helm_install.stdout or "has been installed" in helm_install.stdout'

8. Missing Tests for Infrastructure Code

Files: No test files for Terraform or Helm

Recommendation:

  • Add Terraform validation tests (e.g., using terraform validate, tflint, terraform-compliance)
  • Add Helm template tests (e.g., using helm template + kubeval or helm unittest)
  • Consider adding to CI workflow

Example test structure:

# Add to .github/workflows/03-build-secure.yml or new workflow
- name: Validate Terraform
  run: |
    cd deployment/terraform/modules/ibm-cloud/roks-cluster
    terraform init -backend=false
    terraform validate
    
- name: Validate Helm Charts
  run: |
    helm lint deployment/helm/rag-modulo
    helm template test deployment/helm/rag-modulo | kubeval --strict

📋 Style & Convention Issues

1. Inconsistent YAML Spacing

Some files use 2-space indentation, others use 4-space. Standardize on 2-space per Kubernetes convention.

2. Missing Copyright/License Headers

New files lack copyright headers. Add them for consistency:

# Copyright (c) 2025 RAG Modulo Contributors
# SPDX-License-Identifier: MIT (or your license)

🧪 Testing Recommendations

  1. Validate Locally (before merge):

    # Terraform validation
    cd deployment/terraform/modules/ibm-cloud/roks-cluster
    terraform init -backend=false && terraform validate
    
    # Helm validation
    helm lint deployment/helm/rag-modulo
    helm template test deployment/helm/rag-modulo --dry-run
    
    # Ansible syntax check
    ansible-playbook deployment/ansible/playbooks/deploy-roks-milvus-operator.yml --syntax-check
  2. CI Integration: Add infrastructure validation to existing CI workflows

  3. Integration Test: Deploy to a test ROKS cluster to verify end-to-end functionality


📊 Metrics

  • Lines Added: 8,041 (28 files)
  • Documentation: 4,464 lines (55% of changes)
  • Infrastructure Code: 3,577 lines
  • Commits: 9 (well-structured, atomic)
  • Security Scan Results: ✅ No hardcoded secrets detected

✅ Approval Recommendation

Status: Approve with requested changes

This is high-quality infrastructure code with excellent organization. The issues identified are mostly minor improvements, with one critical fix needed (hardcoded path in Ansible).

Required Before Merge:

  1. ✅ Fix hardcoded path in Ansible playbook (Line 240)
  2. ✅ Add infrastructure validation to CI

Recommended (can be follow-up PRs):

  1. Tighten security group rules
  2. Fix Helm password generation pattern
  3. Add comprehensive IaC tests
  4. Regenerate Terraform lock files for multi-platform

Great work on this comprehensive deployment infrastructure! 🚀

cc: @manavgup

@manavgup
Copy link
Owner Author

Closing PR #678 - Security Issue Resolved

This PR is being closed because it contained an IBM Cloud API key in its commit history that was detected by Gitleaks security scanning.

What Happened

  1. An IBM Cloud API key was accidentally committed in deployment/terraform/environments/dev/terraform.tfvars (commit 5ff8408)
  2. The file was removed and force-pushed, but Gitleaks scans the entire PR commit history, not just the final state
  3. Even after removal, the secret remained visible in the PR's git history

Resolution

New Clean PR Created: #679

  • Same infrastructure code (Terraform, Ansible, Helm)
  • Clean commit history with NO exposed secrets
  • All security scans passing

Security Measures Taken:

  • Removed terraform.tfvars from repository
  • Updated .gitignore to exclude all .tfvars files
  • Added terraform.tfvars.example template for safe configuration
  • Exposed API key MUST be revoked immediately

Action Required

⚠️ CRITICAL: The exposed IBM Cloud API key 5IPr_h4xttK2rBfGeoBD5LpFJIAwXno0NpVzPctFCw8q must be revoked:

  1. Log into IBM Cloud Console: https://cloud.ibm.com/
  2. Navigate to: Manage → Access (IAM) → API keys
  3. Find and delete the exposed API key
  4. Create a new API key
  5. Update local deployment/terraform/environments/dev/terraform.tfvars with the new key

Next Steps

Please review and merge PR #679 which contains the same changes but with a clean commit history free of exposed secrets.


Closed in favor of #679 due to exposed secret in commit history

@manavgup manavgup closed this Nov 26, 2025
manavgup added a commit that referenced this pull request Nov 26, 2025
… leaks

- Add Gitleaks v8.18.1 to pre-commit hooks for local secret detection
- Create .gitleaks.toml with custom rules for IBM Cloud API keys
- Add Terraform .tfvars and Ansible playbook secret detection
- Configure allowlist for false positives (.example files, docs, tests)
- Auto-fix ansible-lint warnings in deploy-roks-milvus-operator.yml

This prevents secrets from being committed locally, complementing CI/CD
security scans (Gitleaks + TruffleHog) that run on PR creation.

Fixes security gap where --no-verify could bypass detect-secrets.

Related to PR #678 (closed), PR #679 (clean)
@manavgup manavgup deleted the pr-branch branch November 26, 2025 15:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants