This project uses Laravel Pint with the Laravel preset to enforce PSR-12 coding standards.
php artisan boost:add-skill appwrite-labs/php-k8s
Save this content to: AGENTS.md
## Purpose
- **Project:** PHP client for Kubernetes clusters with HTTP/WebSocket support, CRD ergonomics, exec/logs/watch, and JSON Patch/Merge Patch.
- **Audience:** Human contributors and code agents working on features, fixes, or docs.
## Quick Repo Map
- `src/KubernetesCluster.php`: Core client; builds URLs, performs operations (get/create/replace/delete, exec, attach, watch, logs, patch).
- `src/Kinds/*`: First‑class resource wrappers (Pod, Deployment, Service, …) extending `K8sResource` with convenience traits.
- `src/Traits/Cluster/*`: HTTP/WebSocket, auth, kubeconfig loaders, version checks.
- `src/Auth/*`: Token providers (ExecCredential, EKS, OpenShift OAuth, ServiceAccount TokenRequest) with automatic refresh.
- `src/Traits/Resource/*`: Reusable capabilities (spec/status/labels/annotations/templates/scale/etc.).
- `src/K8s.php`: Facade/helper for resource construction, YAML parsing, and CRD registration via macros.
- `src/Patches/*`: `JsonPatch` (RFC 6902) and `JsonMergePatch` (RFC 7396).
- `tests/*`: PHPUnit tests (unit + integration) including testing‑only CRDs under `tests/Kinds`.
## Code Style Requirements
This project uses [Laravel Pint](https://laravel.com/docs/pint) with the Laravel preset to enforce PSR-12 coding standards.
**CRITICAL: Always run Pint before committing PHP code changes:**
```bash
./vendor/bin/pint
```
Pint auto-fixes:
- String concatenation spacing (no spaces around `.`)
- Negation operator spacing (space after `!`)
- Trailing commas in multiline arrays
- Doc block formatting
- Use statement ordering
- Class definition formatting
- PSR-12 compliance
**Manual checks after running Pint:**
1. Doc comments must end with periods: `/** Comment. */`
2. No blank lines before `finally` blocks
**If StyleCI reports issues on PR:**
1. Run `./vendor/bin/pint`
2. Fix any remaining manual issues
3. Commit and push fixes
## Stack & Requirements
- **PHP:** `^8.3` (CI also exercises 8.5).
- **Composer deps:** Guzzle 7, Symfony Process 7.3, Illuminate components, Ratchet Pawl, ext‑json; optional `ext-yaml` for YAML helpers, optional `aws/aws-sdk-php` for native EKS authentication.
- **Static analysis:** Psalm (see `psalm.xml`).
- **License:** Apache‑2.0.
- **Authentication:** Supports tokens, certificates, kubeconfig, in-cluster config, exec credential plugins, AWS EKS native, OpenShift OAuth, and ServiceAccount TokenRequest API.
## Local Dev Setup
- **Install deps:** `composer install`.
- **Update deps:** `composer update`.
- **Run all tests:** `vendor/bin/phpunit`.
- **Run tests (unit only):** `vendor/bin/phpunit --filter Test$` (or target specific files) to avoid cluster requirements.
- **Run specific test file:** `vendor/bin/phpunit tests/PriorityClassTest.php`.
- **Run specific test method:** `vendor/bin/phpunit tests/PriorityClassTest.php --filter test_priority_class_build`.
- **Run with CI environment:** `CI=true vendor/bin/phpunit` (requires running Kubernetes cluster).
- **Static analysis:** `vendor/bin/psalm`.
- **Coding style:** Run `./vendor/bin/pint` before all commits (see "Code Style Requirements" above).
## Running Full Integration Tests Locally
These hit a live Kubernetes cluster and mirror CI.
- **Start cluster:** Minikube is the reference. Example: `minikube start --kubernetes-version=v1.34.6`.
- **Enable addons:** `minikube addons enable volumesnapshots && minikube addons enable csi-hostpath-driver && minikube addons enable metrics-server`.
- **Install VPA:** Clone `kubernetes/autoscaler` and run `./vertical-pod-autoscaler/hack/vpa-up.sh`. Alternatively:
```bash
git clone https://github.com/kubernetes/autoscaler.git /tmp/autoscaler
kubectl apply -f /tmp/autoscaler/vertical-pod-autoscaler/deploy/vpa-v1-crd-gen.yaml
kubectl apply -f /tmp/autoscaler/vertical-pod-autoscaler/deploy/recommender-deployment.yaml
kubectl apply -f /tmp/autoscaler/vertical-pod-autoscaler/deploy/updater-deployment.yaml
kubectl apply -f /tmp/autoscaler/vertical-pod-autoscaler/deploy/admission-controller-deployment.yaml
```
- **Install CRDs:**
- Sealed Secrets CRD: `kubectl apply -f https://raw.githubusercontent.com/bitnami-labs/sealed-secrets/main/helm/sealed-secrets/crds/bitnami.com_sealedsecrets.yaml`
- Gateway API: `kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.3.0/standard-install.yaml`
- **Expose API:** `kubectl proxy --port=8080 --reject-paths="^/non-existent-path" &` (tests use `http://127.0.0.1:8080`).
- **Verify connectivity:** `curl -s http://127.0.0.1:8080/version`.
- **Run tests:** `CI=true vendor/bin/phpunit`.
- **Important:** Tests expect the Kubernetes API accessible at `http://127.0.0.1:8080` (see `tests/TestCase.php`).
## Key Concepts
- **Resources:** Each kind extends `Kinds\K8sResource` and composes traits from `Traits\Resource` for spec/status/metadata helpers.
- Resource pattern: `K8sResource` (base) → Uses Traits (HasSpec, HasStatus, etc.) → Implements Contracts (InteractsWithK8sCluster, Watchable, etc.) → Extended by specific classes (K8sPod, K8sDeployment, etc.)
- Namespaced resources: Set `protected static $namespaceable = true` (most resources)
- Cluster-scoped resources: Set `protected static $namespaceable = false` (nodes, PriorityClass, ClusterRole, etc.)
- **Traits:** Provide composable functionality (`src/Traits/Resource/`)
- `HasSpec` - Manage spec section (most resources)
- `HasStatus` - Read-only status information
- `HasSelector` - Label/field selectors
- `HasMetadata` - Labels, annotations, name, namespace
- `HasReplicas` - Replica management (Deployments, StatefulSets, ReplicaSets)
- `HasPodTemplate` - Pod template spec (workload resources)
- `HasStorage` - Storage configuration (PVCs, PVs)
- **Contracts (Interfaces):** Define capabilities (`src/Contracts/`)
- `InteractsWithK8sCluster` - Basic CRUD operations (get, create, update, delete)
- `Watchable` - Watch operations (event streaming)
- `Scalable` - Scale subresource support
- `Loggable` - Log retrieval (pods, jobs)
- `Executable` - Exec operations (pods)
- **Cluster Ops:** `KubernetesCluster` provides typed creators/getters (e.g., `pod()`, `getPodByName()`, `getAllPods()`), plus `exec`, `attach`, `watch`, `logs`, and patch operations.
- **YAML helpers:** `K8s::fromYaml($cluster, $yaml)` and `K8s::fromYamlFile($cluster, $path)` create object(s) from YAML. Templating is supported via `fromTemplatedYamlFile`.
- **CRDs:** Register custom kinds at runtime with `K8s::registerCrd(YourClass::class, 'alias')` or rely on the unique CRD macro computed from kind + apiVersion.
- **Patching:** Use `$resource->jsonPatch($patch)` or `$resource->jsonMergePatch($patch)` with `Patches\JsonPatch`/`JsonMergePatch` or raw arrays.
- **State tracking:** `isSynced()` - resource has been synced with cluster; `exists()` - resource currently exists in cluster.
## Common Tasks
- **Add a new built-in kind:**
1. Create `src/Kinds/K8sYourKind.php` extending `K8sResource`:
```php
<?php
namespace RenokiCo\PhpK8s\Kinds;
use RenokiCo\PhpK8s\Contracts\InteractsWithK8sCluster;
class K8sYourKind extends K8sResource implements InteractsWithK8sCluster
{
protected static $kind = 'YourKind';
protected static $defaultVersion = 'v1'; // or appropriate apiVersion
protected static $namespaceable = true; // or false for cluster-scoped
// Add resource-specific methods
}
```
2. Add factory method in `src/Traits/InitializesResources.php`:
```php
public static function yourKind($cluster = null, array $attributes = [])
{
return new K8sYourKind($cluster, $attributes);
}
```
3. Create test file `tests/YourKindTest.php` with:
- Unit tests: `test_your_kind_build()`, `test_your_kind_from_yaml()`
- Integration test: `test_your_kind_api_interaction()`
- Run methods: `runCreationTests()`, `runGetAllTests()`, `runGetTests()`, `runUpdateTests()`, `runWatchAllTests()`, `runWatchTests()`, `runDeletionTests()`
- Note: Cluster-scoped resources typically omit watch tests
4. Create YAML fixture in `tests/yaml/yourkind.yaml` for YAML parsing tests
5. **Document the resource** (REQUIRED):
```bash
# Generate documentation stub (determines category from class name or specify manually)
php scripts/generate-resource-doc.php K8sYourKind category
# Edit generated file: docs/resources/category/yourkind.yaml.md
# Add to sidebar in docs/.vitepress/config.mjs
# Verify: npm run docs:build
```
- **Test structure:** (`tests/TestCase.php` sets up cluster at `http://127.0.0.1:8080`)
- Build test: Verify resource construction with fluent API
- YAML test: Load and validate from YAML file
- API interaction test: Orchestrate full CRUD lifecycle
- Creation tests: Create resource, verify `isSynced()` and `exists()`
- Deletion tests: Delete resource, wait for deletion, expect `KubernetesAPIException` on get
- **Add support for a CRD (without bundling it):**
- Create a kind class under `tests/Kinds` (for testing) or a separate package.
- Register with `K8s::registerCrd(...)` in tests or userland.
- Provide YAML examples for `K8s::fromYaml*()` parsing.
- **Extend cluster operations:** Add behavior in `Traits/Cluster/*` or `Traits/RunsClusterOperations.php` with matching tests.
## Documentation
- **VitePress setup:** Documentation is in `docs/` with config at `docs/.vitepress/config.mjs`. Deployed to `https://php-k8s.cuppett.dev` via GitHub Actions.
- **Local preview:** `npm install` (once), then `npm run docs:dev` (opens http://localhost:5173).
- **Build check:** `npm run docs:build` to verify docs compile (required before commits touching docs).
- **Adding new resource docs:**
1. Generate stub: `php scripts/generate-resource-doc.php K8sYourKind category`
2. Edit generated `docs/resources/category/yourkind.md` using the template as a guide
3. Add to sidebar in `docs/.vitepress/config.mjs` under the appropriate section
4. Build and verify: `npm run docs:build` and `npm run docs:dev`
- **Documentation coverage check:** Run `php scripts/check-documentation.php` before PRs to ensure all resources are documented.
- **Templates:** Use `docs/_templates/resource-template.md` or `docs/_templates/example-template.md` for new pages.
- **Attribution:** Adapted upstream pages include footer: `*Originally from renoki-co/php-k8s documentation, adapted for cuppett/php-k8s fork*`. New fork-only pages use: `*Documentation for cuppett/php-k8s fork*`.
- **Deployment:** Documentation auto-deploys when changes to `docs/**` are merged to `main`. See `.github/workflows/docs-deploy.yml`.
- **See also:** `DOCS_README.md` for full documentation system overview, `docs/development/documentation.md` for maintenance guide.
## Style & Quality
- **Tests first:** Add/adjust tests for all behavior changes. Use PHPUnit; integration tests may require a live cluster.
- **API stability:** Follow SemVer; avoid breaking public APIs. Prefer additive changes.
- **Consistency:** Mirror naming and patterns used by existing kinds and traits. Keep methods fluent and chainable where appropriate.
- **Docs:** Update `README.md` and/or add focused docs in `docs/` for new features. Keep examples runnable.
- **Static analysis:** Keep Psalm clean (config at `psalm.xml`).
## PR Checklist
- **Code style:** Run `./vendor/bin/pint` and fix any manual style issues before committing.
- `composer install` completes and `vendor/bin/psalm` passes.
- `vendor/bin/phpunit` passes for unit tests; integration suite passes if you ran a local cluster.
- **Documentation complete:**
- New resources have documentation: `php scripts/check-documentation.php`
- Documentation builds successfully: `npm run docs:build`
- Sidebar updated in `docs/.vitepress/config.mjs` if new pages added
- Code examples in docs are tested and work
- Attribution footer present on all pages
- Public APIs documented; new options/settings covered with tests and examples.
- Changes are scoped; one concern per PR.
## Gotchas
- **Cluster URL:** Tests default to `http://127.0.0.1:8080` via `kubectl proxy` and disable SSL verification for local runs.
- **Namespace handling:** Cluster-scoped resources (`$namespaceable = false`) should not include namespace in specs or API calls.
- **YAML extension:** `ext-yaml` is optional but required for YAML helpers (parsing/serialization). Guard features accordingly. Tests using `fromYamlFile()` will fail without the yaml PHP extension installed.
- **kubectl Proxy:** Integration tests expect proxy on `http://127.0.0.1:8080` - verify with `curl http://127.0.0.1:8080/version`.
- **Watch tests:** Cluster-scoped resources typically don't implement watch tests (pattern varies).
- **Status vs Spec:** Status is read-only from API; modifications go in spec section.
- **WebSockets:** Exec/attach/watch rely on Ratchet Pawl; ensure TLS headers/certs are passed through from `KubernetesCluster` when touching WS paths.
- **Patches:** Use proper content types (`application/json-patch+json` vs `application/merge-patch+json`). The client handles this if you use the provided patch helpers.
## Current Resource Types (33+)
- **Workload:** Pod, Deployment, StatefulSet, DaemonSet, Job, CronJob, ReplicaSet
- **Networking:** Service, Ingress, NetworkPolicy, EndpointSlice
- **Storage:** PersistentVolume, PersistentVolumeClaim, StorageClass
- **Configuration:** ConfigMap, Secret
- **Autoscaling:** HorizontalPodAutoscaler, VerticalPodAutoscaler
- **Policy:** ResourceQuota, LimitRange, PodDisruptionBudget, NetworkPolicy, PriorityClass
- **RBAC:** ServiceAccount, Role, ClusterRole, RoleBinding, ClusterRoleBinding
- **Webhooks:** ValidatingWebhookConfiguration, MutatingWebhookConfiguration
- **Cluster:** Namespace, Node, Event
## Kubernetes API Versions Reference
- Core resources (Pod, Service, etc.): `v1`
- Apps resources (Deployment, StatefulSet, etc.): `apps/v1`
- Networking: `networking.k8s.io/v1`
- Autoscaling: `autoscaling/v2` (HPA), `autoscaling.k8s.io/v1` (VPA)
- Scheduling: `scheduling.k8s.io/v1`
- Policy: `policy/v1`
- RBAC: `rbac.authorization.k8s.io/v1`
## Development Workflow (Fork-Specific)
- **Main branch:** `master` (upstream: renoki-co/php-k8s)
- **Fork:** `cuppett/php-k8s` with branch `main`
- **Feature branches:** Use descriptive names (e.g., `feat/add-core-policy-resources`)
- **Pull request process:**
1. Create feature branch from current working branch
2. Implement changes following existing patterns
3. Run full test suite locally: `vendor/bin/phpunit`
4. Run integration tests with minikube: `CI=true vendor/bin/phpunit`
5. Commit changes with descriptive message
6. Push to fork: `git push -u origin {branch-name}`
7. Create PR against `cuppett/php-k8s` main branch: `gh pr create --repo cuppett/php-k8s --base main --title "..." --body "..."`
## Releasing & CI (Reference)
- CI matrix runs PHP 8.3-8.5 across Kubernetes v1.33.10, v1.34.6, v1.35.3 and Laravel 12/13 with both `prefer-lowest` and `prefer-stable`.
- Minikube v1.37.0 is provisioned in CI with VolumeSnapshots, CSI hostpath, metrics‑server, VPA, Sealed Secrets CRD, and Gateway API CRDs before running tests.
- Timeout: 25 minutes per job.
## Useful References
- **Fork Documentation:** https://php-k8s.cuppett.dev
- **Upstream Documentation:** https://php-k8s.renoki.org
- **Fork Repository:** https://github.com/cuppett/php-k8s
- **Upstream Repository:** https://github.com/renoki-co/php-k8s
- **Kubernetes API Reference:** https://kubernetes.io/docs/reference/kubernetes-api/
If anything is unclear or you need deeper context for a change, open a draft PR with your approach and questions. Keeping changes small and well‑tested speeds up reviews.
src/KubernetesCluster.php: Core client; builds URLs, performs operations (get/create/replace/delete, exec, attach, watch, logs, patch).src/Kinds/*: First‑class resource wrappers (Pod, Deployment, Service, …) extending K8sResource with convenience traits.src/Traits/Cluster/*: HTTP/WebSocket, auth, kubeconfig loaders, version checks.src/Auth/*: Token providers (ExecCredential, EKS, OpenShift OAuth, ServiceAccount TokenRequest) with automatic refresh.src/Traits/Resource/*: Reusable capabilities (spec/status/labels/annotations/templates/scale/etc.).src/K8s.php: Facade/helper for resource construction, YAML parsing, and CRD registration via macros.src/Patches/*: JsonPatch (RFC 6902) and JsonMergePatch (RFC 7396).tests/*: PHPUnit tests (unit + integration) including testing‑only CRDs under tests/Kinds.This project uses Laravel Pint with the Laravel preset to enforce PSR-12 coding standards.
CRITICAL: Always run Pint before committing PHP code changes:
./vendor/bin/pint
Pint auto-fixes:
.)!)Manual checks after running Pint:
/** Comment. */finally blocksIf StyleCI reports issues on PR:
./vendor/bin/pint^8.3 (CI also exercises 8.5).ext-yaml for YAML helpers, optional aws/aws-sdk-php for native EKS authentication.psalm.xml).composer install.composer update.vendor/bin/phpunit.vendor/bin/phpunit --filter Test$ (or target specific files) to avoid cluster requirements.vendor/bin/phpunit tests/PriorityClassTest.php.vendor/bin/phpunit tests/PriorityClassTest.php --filter test_priority_class_build.CI=true vendor/bin/phpunit (requires running Kubernetes cluster).vendor/bin/psalm../vendor/bin/pint before all commits (see "Code Style Requirements" above).These hit a live Kubernetes cluster and mirror CI.
minikube start --kubernetes-version=v1.34.6.minikube addons enable volumesnapshots && minikube addons enable csi-hostpath-driver && minikube addons enable metrics-server.kubernetes/autoscaler and run ./vertical-pod-autoscaler/hack/vpa-up.sh. Alternatively:
git clone https://github.com/kubernetes/autoscaler.git /tmp/autoscaler
kubectl apply -f /tmp/autoscaler/vertical-pod-autoscaler/deploy/vpa-v1-crd-gen.yaml
kubectl apply -f /tmp/autoscaler/vertical-pod-autoscaler/deploy/recommender-deployment.yaml
kubectl apply -f /tmp/autoscaler/vertical-pod-autoscaler/deploy/updater-deployment.yaml
kubectl apply -f /tmp/autoscaler/vertical-pod-autoscaler/deploy/admission-controller-deployment.yaml
kubectl apply -f https://raw.githubusercontent.com/bitnami-labs/sealed-secrets/main/helm/sealed-secrets/crds/bitnami.com_sealedsecrets.yamlkubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.3.0/standard-install.yamlkubectl proxy --port=8080 --reject-paths="^/non-existent-path" & (tests use http://127.0.0.1:8080).curl -s http://127.0.0.1:8080/version.CI=true vendor/bin/phpunit.http://127.0.0.1:8080 (see tests/TestCase.php).Kinds\K8sResource and composes traits from Traits\Resource for spec/status/metadata helpers.
K8sResource (base) → Uses Traits (HasSpec, HasStatus, etc.) → Implements Contracts (InteractsWithK8sCluster, Watchable, etc.) → Extended by specific classes (K8sPod, K8sDeployment, etc.)protected static $namespaceable = true (most resources)protected static $namespaceable = false (nodes, PriorityClass, ClusterRole, etc.)src/Traits/Resource/)
HasSpec - Manage spec section (most resources)HasStatus - Read-only status informationHasSelector - Label/field selectorsHasMetadata - Labels, annotations, name, namespaceHasReplicas - Replica management (Deployments, StatefulSets, ReplicaSets)HasPodTemplate - Pod template spec (workload resources)HasStorage - Storage configuration (PVCs, PVs)src/Contracts/)
InteractsWithK8sCluster - Basic CRUD operations (get, create, update, delete)Watchable - Watch operations (event streaming)Scalable - Scale subresource supportLoggable - Log retrieval (pods, jobs)Executable - Exec operations (pods)KubernetesCluster provides typed creators/getters (e.g., pod(), getPodByName(), getAllPods()), plus exec, attach, watch, logs, and patch operations.K8s::fromYaml($cluster, $yaml) and K8s::fromYamlFile($cluster, $path) create object(s) from YAML. Templating is supported via fromTemplatedYamlFile.K8s::registerCrd(YourClass::class, 'alias') or rely on the unique CRD macro computed from kind + apiVersion.$resource->jsonPatch($patch) or $resource->jsonMergePatch($patch) with Patches\JsonPatch/JsonMergePatch or raw arrays.isSynced() - resource has been synced with cluster; exists() - resource currently exists in cluster.src/Kinds/K8sYourKind.php extending K8sResource:
<?php
namespace RenokiCo\PhpK8s\Kinds;
use RenokiCo\PhpK8s\Contracts\InteractsWithK8sCluster;
class K8sYourKind extends K8sResource implements InteractsWithK8sCluster
{
protected static $kind = 'YourKind';
protected static $defaultVersion = 'v1'; // or appropriate apiVersion
protected static $namespaceable = true; // or false for cluster-scoped
// Add resource-specific methods
}
2. Add factory method in `src/Traits/InitializesResources.php`:php
public static function yourKind($cluster = null, array $attributes = [])
{
return new K8sYourKind($cluster, $attributes);
}
3. Create test file `tests/YourKindTest.php` with: - Unit tests: `test_your_kind_build()`, `test_your_kind_from_yaml()` - Integration test: `test_your_kind_api_interaction()` - Run methods: `runCreationTests()`, `runGetAllTests()`, `runGetTests()`, `runUpdateTests()`, `runWatchAllTests()`, `runWatchTests()`, `runDeletionTests()` - Note: Cluster-scoped resources typically omit watch tests 4. Create YAML fixture in `tests/yaml/yourkind.yaml` for YAML parsing tests 5. **Document the resource** (REQUIRED):bash
# Generate documentation stub (determines category from class name or specify manually)
php scripts/generate-resource-doc.php K8sYourKind category
# Add to sidebar in docs/.vitepress/config.mjs
# Verify: npm run docs:build
```
tests/TestCase.php sets up cluster at http://127.0.0.1:8080)
isSynced() and exists()KubernetesAPIException on gettests/Kinds (for testing) or a separate package.K8s::registerCrd(...) in tests or userland.K8s::fromYaml*() parsing.Traits/Cluster/* or Traits/RunsClusterOperations.php with matching tests.docs/ with config at docs/.vitepress/config.mjs. Deployed to https://php-k8s.cuppett.dev via GitHub Actions.npm install (once), then npm run docs:dev (opens http://localhost:5173).npm run docs:build to verify docs compile (required before commits touching docs).php scripts/generate-resource-doc.php K8sYourKind categorydocs/resources/category/yourkind.md using the template as a guidedocs/.vitepress/config.mjs under the appropriate sectionnpm run docs:build and npm run docs:devphp scripts/check-documentation.php before PRs to ensure all resources are documented.docs/_templates/resource-template.md or docs/_templates/example-template.md for new pages.*Originally from renoki-co/php-k8s documentation, adapted for cuppett/php-k8s fork*. New fork-only pages use: *Documentation for cuppett/php-k8s fork*.docs/** are merged to main. See .github/workflows/docs-deploy.yml.DOCS_README.md for full documentation system overview, docs/development/documentation.md for maintenance guide.README.md and/or add focused docs in docs/ for new features. Keep examples runnable.psalm.xml)../vendor/bin/pint and fix any manual style issues before committing.composer install completes and vendor/bin/psalm passes.vendor/bin/phpunit passes for unit tests; integration suite passes if you ran a local cluster.php scripts/check-documentation.phpnpm run docs:builddocs/.vitepress/config.mjs if new pages addedhttp://127.0.0.1:8080 via kubectl proxy and disable SSL verification for local runs.$namespaceable = false) should not include namespace in specs or API calls.ext-yaml is optional but required for YAML helpers (parsing/serialization). Guard features accordingly. Tests using fromYamlFile() will fail without the yaml PHP extension installed.http://127.0.0.1:8080 - verify with curl http://127.0.0.1:8080/version.KubernetesCluster when touching WS paths.application/json-patch+json vs application/merge-patch+json). The client handles this if you use the provided patch helpers.v1apps/v1networking.k8s.io/v1autoscaling/v2 (HPA), autoscaling.k8s.io/v1 (VPA)scheduling.k8s.io/v1policy/v1rbac.authorization.k8s.io/v1master (upstream: renoki-co/php-k8s)cuppett/php-k8s with branch mainfeat/add-core-policy-resources)vendor/bin/phpunitCI=true vendor/bin/phpunitgit push -u origin {branch-name}cuppett/php-k8s main branch: gh pr create --repo cuppett/php-k8s --base main --title "..." --body "..."prefer-lowest and prefer-stable.If anything is unclear or you need deeper context for a change, open a draft PR with your approach and questions. Keeping changes small and well‑tested speeds up reviews.
How can I help you explore Laravel packages today?