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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions .github/workflows/claude-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ jobs:

The PR branch is already checked out in the current working directory.

## Step 0: Check for existing reviews
Run `gh pr view ${{ github.event.pull_request.number }} --json comments --jq '.comments[].body'` and look for "Review for" comments.
If a previous review exists:
- Only report NEW issues on CHANGED lines since last review
- Do NOT repeat previous findings
- Reference previous commit in your new comment if building on prior review

## Step 1: Get the diff and categorize
Run `gh pr diff ${{ github.event.pull_request.number }}` to see all changes.
Categorize files into: DOCS (.mdx, .md), CODE (.js, .ts, .jsx, .tsx), CI (.yml in .github/), CONFIG (other).
Expand Down Expand Up @@ -90,8 +97,13 @@ jobs:
IMPORTANT: Do NOT just say "looks good" or "no issues found" without listing what you actually checked.
A review with no details is UNACCEPTABLE. Show your work.

## Step 4: Update PR description
Add summary between markers <!-- CLAUDE_SUMMARY --> and <!-- /CLAUDE_SUMMARY -->:
## Step 4: Update PR description (preserve existing content)
1. Get current body: `gh pr view ${{ github.event.pull_request.number }} --json body -q .body`
2. ONLY replace content between <!-- CLAUDE_SUMMARY --> and <!-- /CLAUDE_SUMMARY --> markers
3. Keep ALL other PR description content unchanged
4. Update with: `gh pr edit ${{ github.event.pull_request.number }} --body "$UPDATED_BODY"`

Summary format (insert between markers):
```
> [!NOTE]
> One-line summary of PR changes.
Expand All @@ -102,7 +114,7 @@ jobs:
```

claude_args: |
--model claude-opus-4-5-20251101 --mcp-config '{"mcpServers":{"vcluster-yaml":{"command":"npx","args":["-y","vcluster-yaml-mcp-server@latest"]}}}' --allowedTools "Read,Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr view:* | grep:*),Bash(gh api:*),Bash(git diff:*),Bash(git log:*),mcp__github_inline_comment__create_inline_comment,mcp__vcluster-yaml__*"
--model claude-opus-4-5-20251101 --mcp-config '{"mcpServers":{"vcluster-yaml":{"command":"npx","args":["-y","vcluster-yaml-mcp-server@latest"]}}}' --allowedTools "Read,Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr view:* | grep:*),Bash(gh pr edit:*),Bash(gh api:*),Bash(git diff:*),Bash(git log:*),mcp__github_inline_comment__create_inline_comment,mcp__vcluster-yaml__*"

- name: Comment on failure
if: steps.claude-review.outcome == 'failure'
Expand Down
52 changes: 15 additions & 37 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -379,42 +379,20 @@ write them.

### Controlling Vale rules

Disabling all rules

- Use these HTML-style comments to control Vale checking:

```
<!-- vale off --> // Stops all Vale checks
<!-- vale on --> // Resumes Vale checks
```

- Example usage:
```
<!-- vale off -->
<!-- this section ignores all Vale rules -->
This content won't be checked by Vale.
<!-- vale on -->
```

Disabling specific rules

- Target individual rules with this syntax:
```
<!-- vale RuleName = NO --> // Disables one rule
<!-- vale RuleName = YES --> // Re-enables that rule
```

Important formatting requirements:

- Use capital "YES" and "NO"
- Include spaces around the equals sign
- Specify the full rule name

- Example usage:
```
<!-- vale Google.Contractions = NO -->
This section ignores only the contractions rule
<!-- vale Google.Contractions = YES -->
```
Use these HTML-style comments to control Vale checking:

```text
<!-- vale off --> // Stops all Vale checks
<!-- vale on --> // Resumes Vale checks
```

Example usage:

```text
<!-- vale off -->
<!-- this section ignores all Vale rules -->
This content won't be checked by Vale.
<!-- vale on -->
```

<!-- vale on -->
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import ProAdmonition from '../../_partials/admonitions/pro-admonition.mdx'

<ProAdmonition/>

When using [private nodes](../../deploy/worker-nodes/private-nodes/README.mdx), virtual clusters have dedicated worker nodes that are separate from the host cluster. For CI/CD workflows, combine private nodes with [auto-nodes](../../configure/vcluster-yaml/private-nodes/auto-nodes.mdx) so that worker nodes are automatically provisioned when the virtual cluster is created and cleaned up when deleted.

### Prerequisites

Before using private nodes in your GitHub Actions workflow:

1. **vCluster Platform** must be installed and running
2. A **[node provider](/platform/administer/node-providers/overview)** must be configured in vCluster Platform
3. A **virtual cluster template** with private nodes and auto-nodes enabled must be created

### Create a template with private nodes

In vCluster Platform, create a virtual cluster template with private nodes configuration:

```yaml title="Private nodes template configuration"
# Enable private nodes with auto-provisioning
privateNodes:
enabled: true
autoNodes:
# Reference the node provider configured in vCluster Platform
- provider: my-node-provider
dynamic:
- name: ci-node-pool
# Limit the number of nodes for CI workloads
limits:
nodes: "3"

# Control plane configuration
controlPlane:
distro:
k8s:
image:
tag: v1.31.2
service:
spec:
# LoadBalancer required for private nodes connectivity
type: LoadBalancer

# Network configuration required for private nodes
networking:
podCIDR: 10.64.0.0/16
serviceCIDR: 10.128.0.0/16
```

<!-- vale off -->
### Configure GitHub Actions workflow
<!-- vale on -->

This example creates a virtual cluster with private nodes using a Platform template:

```yaml
# .github/workflows/vclusters-private-nodes.yaml
name: Pull Request Checks (Private Nodes)
on:
pull_request:
branches:
- "main"
jobs:
e2e:
runs-on: ubuntu-latest
steps:
- name: Install vCluster CLI
uses: loft-sh/setup-vcluster@main
- name: Login to vCluster Platform instance
env:
LOFT_URL: ${{ secrets.LOFT_URL }}
ACCESS_KEY: ${{ secrets.ACCESS_KEY }}
run: vcluster platform login $LOFT_URL --access-key $ACCESS_KEY
- name: Create PR Virtual Cluster with Private Nodes
env:
NAME: repo-${{ github.event.repository.name }}-pr-${{ github.event.pull_request.number }}
# Use --template to reference the private nodes template
run: vcluster create $NAME --project default --template private-nodes-ci
- name: Wait for nodes to be ready
# Auto-nodes provisions worker nodes; wait for them to join
run: |
echo "Waiting for private nodes to join the cluster..."
kubectl wait --for=condition=Ready nodes --all --timeout=300s
- name: Deploy Application
run: kubectl apply -Rf ./kubernetes
- name: Wait for Deployment
run: kubectl rollout status deployments/the-app
- name: Run Tests
run: make e2e
- name: Delete PR Virtual Cluster
env:
NAME: repo-${{ github.event.repository.name }}-pr-${{ github.event.pull_request.number }}
# Deleting the vCluster also cleans up the auto-provisioned nodes
run: vcluster delete $NAME --project default
```

**Explanation:**

1. The [Setup vCluster](https://github.com/loft-sh/setup-vcluster) action installs the vCluster CLI.
2. The `vcluster platform login` command authenticates to vCluster Platform using [GitHub secrets](https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions).
3. The `vcluster create` command with `--template private-nodes-ci` creates a virtual cluster using the private nodes template. This triggers auto-nodes to provision dedicated worker nodes.
4. Wait for the auto-provisioned nodes to join and become ready before deploying applications.
5. Deploy and test the application on the dedicated private nodes.
6. The `vcluster delete` command removes the virtual cluster and auto-nodes automatically cleans up the provisioned worker nodes.

:::info Node provisioning time
Auto-nodes provisioning typically takes 1-3 minutes depending on your cloud provider. Factor this into your CI/CD pipeline timeouts.
:::
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,30 @@ import PartialIntegrationsVclusterPullRequestManual from '../../_partials/integ
import PartialIntegrationsVclusterPullRequestUse from '../../_partials/integrations/github-actions-vclusters-pull-request-use.mdx'

import PartialIntegrationsPullRequestDevspace from '../../_partials/integrations/github-actions-pull-request-devspace.mdx'
import PartialIntegrationsVclusterPullRequestPrivateNodes from '../../_partials/integrations/github-actions-vclusters-pull-request-private-nodes.mdx'

import TenancySupport from '../../_fragments/tenancy-support.mdx';

<TenancySupport hostNodes="true" />
<TenancySupport hostNodes="true" privateNodes="true" />

<!-- vale off -->
GitHub Actions can be created for the following workflows:
<!-- vale on -->
- [Setup vCluster](https://github.com/loft-sh/setup-vcluster): Installs the `vCluster` CLI
- [Setup DevSpace](https://github.com/loft-sh/setup-devspace): Installs the `DevSpace` CLI

## Deploying virtual clusters on pull requests
## Deploy virtual clusters on pull requests

These examples show how to create and delete Virtual Clusters for pull requests.
Virtual clusters provide isolated Kubernetes environments for each pull request, enabling:

- Parallel testing without resource conflicts between PRs
- Clean environments that don't accumulate state from previous test runs
- Fast creation and deletion compared to provisioning full clusters
- Cost efficiency by sharing underlying infrastructure while maintaining isolation

### Deploy with host nodes

When using [host nodes](../../deploy/worker-nodes/host-nodes/README.mdx), virtual cluster workloads run on the existing host cluster nodes. This is the simplest setup for CI/CD pipelines.

<Tabs
defaultValue="manual"
Expand All @@ -44,6 +56,10 @@ These examples show how to create and delete Virtual Clusters for pull requests.
</TabItem>
</Tabs>

### Deploy with private nodes

<PartialIntegrationsVclusterPullRequestPrivateNodes/>

## DevSpace for running tests on pull requests

<PartialIntegrationsPullRequestDevspace/>