{"id":"2bcc7235-c7ad-4e56-9a31-c8f2e3277a2a","shortId":"Yjmnvf","kind":"skill","title":"kubesphere-devops-tenant","tagline":"Use when operating KubeSphere DevOps as a namespace-scoped tenant with limited permissions, without cluster-admin access, or when accessing DevOps through KubeSphere APIs only","description":"# KubeSphere DevOps Tenant Operations\n\n## Overview\n\nThis guide covers DevOps operations for **namespace-scoped tenants** who:\n- Have admin/operator permissions within their DevOpsProject namespace(s)\n- **Cannot** access `kubesphere-devops-system` (Jenkins secrets, tokens)\n- **Cannot** call Jenkins APIs directly\n- Must use **KubeSphere APIs** (`/kapis/devops.kubesphere.io/`) for all operations\n- Use **KubeSphere authentication** (OAuth tokens), not Jenkins tokens\n\n**Critical Distinction:** DevOps projects are **namespaces**, not DevOpsProject CRs. To list accessible DevOps projects:\n```bash\n# Correct - lists namespaces (DevOps projects) tenant can access\nGET /clusters/{cluster}/kapis/devops.kubesphere.io/v1alpha3/workspaces/{workspace}/namespaces\n\n# Wrong - requires cluster-admin, returns 403 for tenants\nGET /clusters/{cluster}/apis/devops.kubesphere.io/v1alpha3/devopsprojects\n```\n\n## When to Use\n\n- Operating as a project admin/operator (not cluster admin)\n- Working within tenant namespace boundaries\n- No access to Jenkins secrets in `kubesphere-devops-system`\n- Need to trigger pipelines via KubeSphere API\n- Building automation for namespace-scoped users\n- Developing tenant-facing tooling\n\n## Tenant vs Admin Permissions\n\n| Capability | Tenant (Namespace) | Admin (Cluster) |\n|------------|-------------------|-----------------|\n| Access DevOpsProject | ✅ Own namespace(s) | ✅ All namespaces |\n| Create/Edit Pipelines | ✅ In own namespace | ✅ Any namespace |\n| View PipelineRuns | ✅ In own namespace | ✅ Any namespace |\n| Access Jenkins Secret | ❌ No | ✅ `kubesphere-devops-system` |\n| Direct Jenkins API | ❌ No | ✅ Full access |\n| View Jenkins Console | ❌ No | ✅ Via NodePort |\n| KubeSphere API | ✅ `/kapis/` | ✅ `/kapis/` |\n\n## Authentication\n\nTenants authenticate via KubeSphere's OAuth, not Jenkins. See [kubesphere-core](../../core/kubesphere-core/SKILL.md) for complete OAuth authentication details.\n\n### Quick Reference\n\n```bash\n# Exchange credentials for OAuth token (see core skill for details)\nexport KUBESPHERE_API=\"https://kubesphere-api.example.com\"\nexport USERNAME=\"tenant-user\"\nexport PASSWORD=\"tenant-password\"\n\n# Get token\nexport API_TOKEN=$(curl -s -X POST \"${KUBESPHERE_API}/oauth/token\" \\\n  -H \"Content-Type: application/x-www-form-urlencoded\" \\\n  -d \"grant_type=password&username=${USERNAME}&password=${PASSWORD}&client_id=kubesphere&client_secret=kubesphere\" \\\n  | jq -r '.access_token')\n\n# Use token\ncurl -s \"${KUBESPHERE_API}/kapis/devops.kubesphere.io/v1alpha3/namespaces/demo-project/pipelines\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\"\n```\n\n**Key Points:**\n- OAuth token expires in 7200 seconds (2 hours)\n- Use `client_id=kubesphere` and `client_secret=kubesphere`\n- Token contains user's RBAC permissions\n\nSee [kubesphere-core](../../core/kubesphere-core/SKILL.md#authentication) for complete OAuth authentication details including token refresh and common use cases.\n\n### Get KubeSphere API Token\n\nTenants authenticate via KubeSphere's OAuth, not Jenkins:\n\n```bash\n# Method 1: Using kubeconfig (if configured)\nkubectl config view --raw -o jsonpath='{.users[?(@.name==\"current-user\")].user.token}'\n\n# Method 2: Via KubeSphere OAuth API (Recommended)\nexport KUBESPHERE_URL=\"https://kubesphere-api.example.com\"\nexport USERNAME=\"tenant-user\"\nexport PASSWORD=\"tenant-password\"\n\n# Exchange credentials for token\nTOKEN_RESPONSE=$(curl -s -X POST \"${KUBESPHERE_URL}/oauth/token\" \\\n  -H \"Content-Type: application/x-www-form-urlencoded\" \\\n  --data-urlencode \"grant_type=password\" \\\n  --data-urlencode \"username=${USERNAME}\" \\\n  --data-urlencode \"password=${PASSWORD}\" \\\n  --data-urlencode \"client_id=kubesphere\" \\\n  --data-urlencode \"client_secret=kubesphere\")\n\n# Extract access token\nACCESS_TOKEN=$(echo \"$TOKEN_RESPONSE\" | jq -r '.access_token')\n\n# Token expires in 7200 seconds (2 hours)\necho \"Token obtained: ${ACCESS_TOKEN:0:50}...\"\n```\n\n### Using Token with API\n\n```bash\nexport API_TOKEN=\"<your-kubesphere-token>\"\nexport DEVOPS_PROJECT=\"demo-project\"\nexport KUBESPHERE_API=\"https://kubesphere-api.example.com\"\n\n# Verify access\ncurl -s \"${KUBESPHERE_API}/kapis/devops.kubesphere.io/v1alpha2/namespaces/${DEVOPS_PROJECT}/pipelines\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\"\n```\n\n## Complete Working Example\n\nHere's a verified workflow using tenant credentials (stoneshi / P@88w0rd):\n\n### Step 1: Authenticate\n```bash\nexport KUBESPHERE_API=\"http://kubesphere-apiserver.kubesphere-system.svc:80\"\nexport USERNAME=\"stoneshi\"\nexport PASSWORD='P@88w0rd'\n\n# Get OAuth token\nTOKEN_RESPONSE=$(curl -s -X POST \"${KUBESPHERE_API}/oauth/token\" \\\n  -H \"Content-Type: application/x-www-form-urlencoded\" \\\n  -d \"grant_type=password\" \\\n  -d \"username=${USERNAME}\" \\\n  -d \"password=${PASSWORD}\" \\\n  -d \"client_id=kubesphere\" \\\n  -d \"client_secret=kubesphere\")\n\nexport API_TOKEN=$(echo \"$TOKEN_RESPONSE\" | jq -r '.access_token')\necho \"Authenticated as: $(curl -s ${KUBESPHERE_API}/kapis/iam.kubesphere.io/v1beta1/users/stoneshi -H \"Authorization: Bearer ${API_TOKEN}\" | jq -r '.metadata.name')\"\n```\n\n### Step 2: Access Workspace Resources\n```bash\n# Verify workspace access (returns \"stone\")\ncurl -s \"${KUBESPHERE_API}/kapis/tenant.kubesphere.io/v1beta1/workspaces/stone\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" | jq -r '.metadata.name'\n\n# Try accessing other workspace (returns 403 Forbidden - correct tenant isolation)\ncurl -s \"${KUBESPHERE_API}/kapis/tenant.kubesphere.io/v1beta1/workspaces/demo\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\"\n# Output: {\"message\":\"workspaces.tenant.kubesphere.io \\\"demo\\\" is forbidden...\"}\n```\n\n### Step 3: Create and List Pipelines\n```bash\nexport DEVOPS_PROJECT=\"stone-devops\"  # Must be in \"stone\" workspace\n\n# List pipelines in tenant namespace\ncurl -s \"${KUBESPHERE_API}/kapis/devops.kubesphere.io/v1alpha3/namespaces/${DEVOPS_PROJECT}/pipelines\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" | jq -r '.items[] | \"✓ \" + .metadata.name'\n\n# Create pipeline via kubectl (as tenant with namespace permissions)\ncat <<EOF | kubectl apply -f -\napiVersion: devops.kubesphere.io/v1alpha3\nkind: Pipeline\nmetadata:\n  name: stone-tenant-pipeline\n  namespace: stone-devops\nspec:\n  type: pipeline\n  pipeline:\n    name: stone-tenant-pipeline\n    description: \"Test pipeline for tenant verification\"\n    jenkinsfile: |\n      pipeline {\n        agent { label \"base\" }\n        stages {\n          stage(\"Test\") {\n            steps {\n              sh \"echo 'Hello from tenant pipeline'\"\n            }\n          }\n        }\n      }\nEOF\n\n# Verify via API\ncurl -s \"${KUBESPHERE_API}/kapis/devops.kubesphere.io/v1alpha3/namespaces/${DEVOPS_PROJECT}/pipelines/stone-tenant-pipeline\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" | jq -r '{name: .metadata.name, type: .spec.type}'\n```\n\n### Step 4: Trigger and Monitor Run\n```bash\nexport PIPELINE_NAME=\"stone-tenant-pipeline\"\n\n# Trigger run\ncurl -s -X POST \"${KUBESPHERE_API}/kapis/devops.kubesphere.io/v1alpha2/namespaces/${DEVOPS_PROJECT}/pipelines/${PIPELINE_NAME}/runs\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{}' | jq -r '{runId: .id, state: .state}'\n\n# List runs (Blue Ocean format)\ncurl -s \"${KUBESPHERE_API}/kapis/devops.kubesphere.io/v1alpha2/namespaces/${DEVOPS_PROJECT}/pipelines/${PIPELINE_NAME}/runs\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" | jq '.items[] | {id: .id, state: .state, result: .result}'\n\n# Check specific run status\nexport RUN_ID=\"1\"\ncurl -s \"${KUBESPHERE_API}/kapis/devops.kubesphere.io/v1alpha2/namespaces/${DEVOPS_PROJECT}/pipelines/${PIPELINE_NAME}/runs/${RUN_ID}\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" | jq -r '{state: .state, result: .result, duration: .durationInMillis}'\n# Output: {\"state\":\"FINISHED\",\"result\":\"SUCCESS\",\"duration\":15110}\n```\n\n### Step 5: Get Logs\n```bash\n# Get console log (tenant accessible, no Jenkins token needed)\ncurl -s \"${KUBESPHERE_API}/kapis/devops.kubesphere.io/v1alpha2/namespaces/${DEVOPS_PROJECT}/pipelines/${PIPELINE_NAME}/runs/${RUN_ID}/log\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" | tail -20\n\n# Expected output includes:\n# + echo Hello from tenant pipeline\n# Hello from tenant pipeline\n# Finished: SUCCESS\n```\n\n### Key Findings\n\n| Aspect | Tenant Behavior |\n|--------|-----------------|\n| **Authentication** | OAuth with client_id/client_secret = \"kubesphere\" |\n| **Token Expiry** | 7200 seconds (2 hours) |\n| **API Version** | v1alpha3 for pipelines, v1alpha2 for runs |\n| **Response Format** | Blue Ocean JSON (not Kubernetes resources) |\n| **Status Fields** | `.state` (QUEUED/RUNNING/FINISHED), `.result` (SUCCESS/FAILURE) |\n| **Namespace Isolation** | 403 Forbidden for other workspaces |\n| **Logs Access** | ✅ Available via KubeSphere API |\n| **Artifacts** | ✅ Available via `/artifacts` endpoint |\n\n## Pipeline Operations\n\n### List Pipelines (Tenant View)\n\n```bash\ncurl -s \"${KUBESPHERE_API}/kapis/devops.kubesphere.io/v1alpha2/search?q=type:pipeline\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\"\n\n# Or list in specific namespace\n# Via API (v1alpha3 for pipelines)\ncurl -s \"${KUBESPHERE_API}/kapis/devops.kubesphere.io/v1alpha3/namespaces/${DEVOPS_PROJECT}/pipelines\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" | jq -r '.items[].metadata.name'\n  -H \"Authorization: Bearer ${API_TOKEN}\" | jq '.items[].metadata.name'\n```\n\n### Get Pipeline Details\n\n```bash\nexport PIPELINE_NAME=\"my-pipeline\"\n\ncurl -s \"${KUBESPHERE_API}/kapis/devops.kubesphere.io/v1alpha3/namespaces/${DEVOPS_PROJECT}/pipelines/${PIPELINE_NAME}\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" | jq .\n```\n\n### Create Pipeline (Tenant)\n\n**Regular Pipeline:**\n```bash\ncurl -s -X POST \"${KUBESPHERE_API}/kapis/devops.kubesphere.io/v1alpha2/namespaces/${DEVOPS_PROJECT}/pipelines\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"apiVersion\": \"devops.kubesphere.io/v1alpha3\",\n    \"kind\": \"Pipeline\",\n    \"metadata\": {\n      \"name\": \"my-tenant-pipeline\",\n      \"namespace\": \"'${DEVOPS_PROJECT}'\"\n    },\n    \"spec\": {\n      \"type\": \"pipeline\",\n      \"pipeline\": {\n        \"name\": \"my-tenant-pipeline\",\n        \"description\": \"Pipeline created by tenant\",\n        \"jenkinsfile\": \"pipeline {\\n  agent { label \\\"base\\\" }\\n  stages {\\n    stage(\\\"Build\\\") {\\n      steps {\\n        sh \\\"echo Building...\\\"\\n      }\\n    }\\n  }\\n}\"\n      }\n    }\n  }'\n```\n\n**Multi-Branch Pipeline:**\n```bash\ncurl -s -X POST \"${KUBESPHERE_API}/kapis/devops.kubesphere.io/v1alpha2/namespaces/${DEVOPS_PROJECT}/pipelines\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"apiVersion\": \"devops.kubesphere.io/v1alpha3\",\n    \"kind\": \"Pipeline\",\n    \"metadata\": {\n      \"name\": \"my-multibranch-pipeline\",\n      \"namespace\": \"'${DEVOPS_PROJECT}'\"\n    },\n    \"spec\": {\n      \"type\": \"multi-branch-pipeline\",\n      \"multi_branch_pipeline\": {\n        \"name\": \"my-multibranch-pipeline\",\n        \"description\": \"Multi-branch pipeline from tenant\",\n        \"source_type\": \"git\",\n        \"git_source\": {\n          \"url\": \"https://github.com/example/repo\",\n          \"credential_id\": \"my-git-credential\",\n          \"discover_branches\": true,\n          \"discover_tags\": false\n        },\n        \"script_path\": \"Jenkinsfile\"\n      }\n    }\n  }'\n```\n\n### Create Multi-Branch Pipeline from Private Repository\n\n> ⚠️ **CRITICAL: Always Check Repository Type First**\n> \n> Before creating any multi-branch pipeline, you **MUST** ask the user:\n> > \"Is this a private repository?\"\n> \n> **If YES (Private Repo):**\n> 1. Ask if they want to use an existing credential or create a new one\n> 2. Create a DevOps credential (`basic-auth` type with GitHub PAT) - see Step 1 below\n> 3. Reference the credential in `git_source.credential_id` when creating the pipeline\n> \n> **If NO (Public Repo):**\n> - Set `credential_id: \"\"` (empty string)\n> \n> Never assume repository type - always confirm with the user first. Never use `GITHUB_` env vars directly in pipeline specs.\n\n**Complete workflow for private GitHub repository:**\n\n**Prerequisites:**\n- GitHub Personal Access Token (PAT) with repo access\n- DevOps project namespace (e.g., `devopstestc2nj7`)\n\n**Step 1: Create Credential for GitHub Access**\n```bash\nexport GITHUB_PAT=\"ghp_xxxxxxxxxxxxxxxxxxxx\"\nexport TENANT_NAME=\"stone-ns-admin\"\n\ncurl -s -X POST \"${KUBESPHERE_API}/clusters/member-1/kapis/devops.kubesphere.io/v1alpha3/namespaces/devopstestc2nj7/credentials\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"apiVersion\": \"v1\",\n    \"kind\": \"Secret\",\n    \"metadata\": {\n      \"name\": \"github-token\",\n      \"namespace\": \"devopstestc2nj7\",\n      \"annotations\": {\n        \"credential.devops.kubesphere.io/type\": \"basic-auth\"\n      }\n    },\n    \"stringData\": {\n      \"username\": \"git\",\n      \"password\": \"'${GITHUB_PAT}'\"\n    },\n    \"type\": \"credential.devops.kubesphere.io/basic-auth\"\n  }'\n```\n\n**Step 2: Create GitRepository**\n```bash\ncurl -s -X POST \"${KUBESPHERE_API}/clusters/member-1/kapis/devops.kubesphere.io/v1alpha3/namespaces/devopstestc2nj7/gitrepositories\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"apiVersion\": \"devops.kubesphere.io/v1alpha3\",\n    \"kind\": \"GitRepository\",\n    \"metadata\": {\n      \"name\": \"my-private-repo\",\n      \"namespace\": \"devopstestc2nj7\"\n    },\n    \"spec\": {\n      \"url\": \"https://github.com/stoneshi-yunify/jenkinsfiles.git\",\n      \"provider\": \"github\",\n      \"secret\": {\n        \"name\": \"github-token\",\n        \"namespace\": \"devopstestc2nj7\"\n      },\n      \"description\": \"Private repository with Jenkinsfile\"\n    }\n  }'\n```\n\n**Step 3: Create Multi-Branch Pipeline**\n```bash\ncurl -s -X POST \"${KUBESPHERE_API}/clusters/member-1/kapis/devops.kubesphere.io/v1alpha3/namespaces/devopstestc2nj7/pipelines\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"apiVersion\": \"devops.kubesphere.io/v1alpha3\",\n    \"kind\": \"Pipeline\",\n    \"metadata\": {\n      \"name\": \"echo-pipeline\",\n      \"namespace\": \"devopstestc2nj7\",\n      \"annotations\": {\n        \"kubesphere.io/creator\": \"'${TENANT_NAME}'\"\n      }\n    },\n    \"spec\": {\n      \"type\": \"multi-branch-pipeline\",\n      \"multi_branch_pipeline\": {\n        \"name\": \"echo-pipeline\",\n        \"description\": \"Multi-branch pipeline from private repo\",\n        \"source_type\": \"git\",\n        \"git_source\": {\n          \"url\": \"https://github.com/stoneshi-yunify/jenkinsfiles.git\",\n          \"credential_id\": \"github-token\",\n          \"discover_branches\": true,\n          \"discover_tags\": false\n        },\n        \"script_path\": \"echo/Jenkinsfile\"\n      }\n    }\n  }'\n```\n\n**Key Points:**\n- GitRepository requires `spec.provider` (e.g., `github`) and `spec.secret` fields\n- Pipeline **MUST** have `kubesphere.io/creator` annotation when created by tenant\n- Multi-branch pipelines auto-discover branches from the repository\n\n## Pipeline Runs (The Tenant Way)\n\n> ⚠️ **API Version Notice**: The `/kapis/devops.kubesphere.io/v1alpha2/` APIs are deprecated. Always prefer `v1alpha3` APIs when available.\n\n### Trigger a Pipeline Run (Multi-Branch)\n\n**For Multi-Branch Pipelines - Three-Step Procedure:**\n\n**Step 1: List Available Branches**\n```bash\ncurl -s \"${KUBESPHERE_API}/clusters/${CLUSTER}/kapis/devops.kubesphere.io/v1alpha3/namespaces/${DEVOPS_PROJECT}/pipelines/${PIPELINE_NAME}/branches?filter=origin&page=1&limit=10\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" \\\n  -H \"Content-Type: application/json\" | jq -r '.items[] | \"- Branch: \\(.name) | Latest: \\(.latestRun.id // \"N/A\") | Status: \\(.latestRun.result // \"N/A\")\"'\n```\n\n**Step 2: Ask User Which Branch**\n> \"Which branch would you like to build?\"\n\n**Step 3: Trigger Build with Branch Parameter**\n```bash\nexport BRANCH=\"main\"  # User's selection\n\ncurl -s -X POST \"${KUBESPHERE_API}/clusters/${CLUSTER}/kapis/devops.kubesphere.io/v1alpha3/namespaces/${DEVOPS_PROJECT}/pipelines/${PIPELINE_NAME}/pipelineruns?branch=${BRANCH}\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"parameters\":[]}' | jq -r '.metadata.name'\n```\n\n**Key Points:**\n- Use `v1alpha3` endpoint with `?branch=${BRANCH}` query parameter\n- Returns Kubernetes PipelineRun resource (not Blue Ocean format)\n- For multi-branch pipelines, the branch parameter is required\n\n### Trigger Repository Scanning (Multi-Branch)\n\n> **Exception to v1alpha3 rule**: Repository scanning uses **v1alpha2** API. This endpoint is not available in v1alpha3.\n\n**When to use:**\n- Force immediate repository re-scan to discover new branches\n- Troubleshoot branch detection issues\n- Manually trigger branch indexing after credential changes\n\n**Step 1: Trigger Scan (v1alpha2)**\n```bash\ncurl -X POST \"${KUBESPHERE_API}/clusters/${CLUSTER}/kapis/devops.kubesphere.io/v1alpha2/namespaces/${DEVOPS_PROJECT}/pipelines/${PIPELINE_NAME}/scan\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{}'\n```\n\n**Step 2: Fetch Scanning Log (v1alpha2)**\n```bash\ncurl -s \"${KUBESPHERE_API}/clusters/${CLUSTER}/kapis/devops.kubesphere.io/v1alpha2/namespaces/${DEVOPS_PROJECT}/pipelines/${PIPELINE_NAME}/consolelog\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\"\n```\n\n**Example scanning output:**\n```\nStarted by user stone-ns-admin\nStarting branch indexing...\n > git ls-remote --symref -- https://github.com/org/repo.git\nFetching & pruning origin...\nChecking branches:\n  Checking branch main ✓\n      'Jenkinsfile' found\n    Met criteria\n  Checking branch feature-branch\n      'Jenkinsfile' found\n    Met criteria\n  Checking branch old-branch\n      'Jenkinsfile' not found\n    Does not meet criteria\nProcessed 3 branches\nFinished branch indexing. Indexing took 3 sec\nFinished: SUCCESS\n```\n\n**Via PipelineRun CR (kubectl) - Alternative:**\n```bash\ncat <<EOF | kubectl apply -f -\napiVersion: devops.kubesphere.io/v1alpha3\nkind: PipelineRun\nmetadata:\n  name: my-run-$(date +%s)\n  namespace: ${DEVOPS_PROJECT}\nspec:\n  pipelineRef:\n    name: ${PIPELINE_NAME}\n  scm:\n    refName: \"main\"    # Branch name for multi-branch pipelines\n    refType: \"branch\"\nEOF\n```\n\n### List Pipeline Runs\n\n```bash\n# Via kubectl (preferred - returns Kubernetes PipelineRun resources)\nkubectl get pipelineruns -n ${DEVOPS_PROJECT} --sort-by=.metadata.creationTimestamp\n\n# Via API (v1alpha3 - returns Kubernetes resources)\ncurl -s \"${KUBESPHERE_API}/clusters/${CLUSTER}/kapis/devops.kubesphere.io/v1alpha3/namespaces/${DEVOPS_PROJECT}/pipelineruns?labelSelector=devops.kubesphere.io/pipeline=${PIPELINE_NAME}\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" | jq '.items[] | {name: .metadata.name, phase: .status.phase, creationTime: .metadata.creationTimestamp}'\n```\n\n### Get Run Status\n\n```bash\n# Via kubectl (preferred)\nkubectl get pipelinerun ${RUN_NAME} -n ${DEVOPS_PROJECT} -o jsonpath='{.status.phase}'\n\n# Via API (v1alpha3)\ncurl -s \"${KUBESPHERE_API}/clusters/${CLUSTER}/kapis/devops.kubesphere.io/v1alpha3/namespaces/${DEVOPS_PROJECT}/pipelineruns/${RUN_NAME}\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" | jq -r '{name: .metadata.name, phase: .status.phase, startTime: .status.startTime, completionTime: .status.completionTime}'\n```\n\n### Deprecated v1alpha2 APIs\n\n> ⚠️ **Deprecated**: These v1alpha2 endpoints return Blue Ocean format and are deprecated. Use v1alpha3 APIs shown above.\n\n```bash\n# List runs (v1alpha2 - deprecated)\ncurl -s \"${KUBESPHERE_API}/kapis/devops.kubesphere.io/v1alpha2/namespaces/${DEVOPS_PROJECT}/pipelines/${PIPELINE_NAME}/runs\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" | jq '.items[] | {id: .id, state: .state, result: .result}'\n\n# Get run status (v1alpha2 - deprecated)\nexport RUN_ID=\"1\"\ncurl -s \"${KUBESPHERE_API}/kapis/devops.kubesphere.io/v1alpha2/namespaces/${DEVOPS_PROJECT}/pipelines/${PIPELINE_NAME}/runs/${RUN_ID}\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" | jq '{id: .id, state: .state, result: .result, duration: .durationInMillis}'\n```\n\n```bash\n# Get concise status (Blue Ocean format fields)\ncurl -s \"${KUBESPHERE_API}/kapis/devops.kubesphere.io/v1alpha2/namespaces/${DEVOPS_PROJECT}/pipelines/${PIPELINE_NAME}/runs/${RUN_ID}\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" | jq -r '{id: .id, state: .state, result: .result, startTime: .startTime, duration: .durationInMillis}'\n\n# Example output:\n# {\n#   \"id\": \"1\",\n#   \"state\": \"FINISHED\",\n#   \"result\": \"SUCCESS\",\n#   \"startTime\": \"2026-03-19T02:50:12.747+0000\",\n#   \"duration\": 15110\n# }\n\n# Watch for completion\nwhile true; do\n  STATUS=$(curl -s \"${KUBESPHERE_API}/kapis/devops.kubesphere.io/v1alpha2/namespaces/${DEVOPS_PROJECT}/pipelines/${PIPELINE_NAME}/runs/${RUN_ID}\" \\\n    -H \"Authorization: Bearer ${API_TOKEN}\" | jq -r '.state')\n  echo \"State: $STATUS\"\n  [[ \"$STATUS\" == \"FINISHED\" ]] && break\n  sleep 5\ndone\n```\n\n```bash\n# Get concise status\ncurl -s \"${KUBESPHERE_API}/kapis/devops.kubesphere.io/v1alpha2/namespaces/${DEVOPS_PROJECT}/pipelines/${PIPELINE_NAME}/runs/${RUN_ID}\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" | jq -r '{state: .status.phase, result: .status.conditions[0].reason, startTime: .status.startTime, completionTime: .status.completionTime}'\n\n# Watch for completion\nwhile true; do\n  STATUS=$(curl -s \"${KUBESPHERE_API}/kapis/devops.kubesphere.io/v1alpha2/namespaces/${DEVOPS_PROJECT}/pipelines/${PIPELINE_NAME}/runs/${RUN_ID}\" \\\n    -H \"Authorization: Bearer ${API_TOKEN}\" | jq -r '.status.phase')\n  echo \"Status: $STATUS\"\n  [[ \"$STATUS\" == \"Succeeded\" || \"$STATUS\" == \"Failed\" ]] && break\n  sleep 5\ndone\n```\n\n## Logs and Artifacts (Tenant Access)\n\n### Get Console Log\n\n**Tenant Method (via KubeSphere API):**\n```bash\ncurl -s \"${KUBESPHERE_API}/kapis/devops.kubesphere.io/v1alpha2/namespaces/${DEVOPS_PROJECT}/pipelines/${PIPELINE_NAME}/runs/${RUN_ID}/log\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\"\n\n# Or with kubectl\nkubectl get pipelinerun ${RUN_ID} -n ${DEVOPS_PROJECT} -o jsonpath='{.status.log}' 2>/dev/null || echo \"Logs via API only\"\n```\n\n**Note:** Console logs may not be available immediately. Poll until ready:\n```bash\nwhile ! curl -s \"${KUBESPHERE_API}/kapis/devops.kubesphere.io/v1alpha2/namespaces/${DEVOPS_PROJECT}/pipelines/${PIPELINE_NAME}/runs/${RUN_ID}/log\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" | grep -q \"Finished:\"; do\n  echo \"Waiting for logs...\"\n  sleep 5\ndone\necho \"Logs ready!\"\n```\n\n### List Artifacts\n\n```bash\ncurl -s \"${KUBESPHERE_API}/kapis/devops.kubesphere.io/v1alpha2/namespaces/${DEVOPS_PROJECT}/pipelines/${PIPELINE_NAME}/runs/${RUN_ID}/artifacts\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" | jq '.[] | {name: .name, path: .path, size: .size}'\n```\n\n### Download Artifacts\n\n**Download via KubeSphere API:**\n```bash\nexport ARTIFACT_NAME=\"service\"\nexport ARTIFACT_PATH=\"service\"\n\n# Get artifact download URL\nARTIFACT_URL=$(curl -s \"${KUBESPHERE_API}/kapis/devops.kubesphere.io/v1alpha2/namespaces/${DEVOPS_PROJECT}/pipelines/${PIPELINE_NAME}/runs/${RUN_ID}/artifacts\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" | jq -r \".[] | select(.name==\\\"${ARTIFACT_NAME}\\\") | .url\")\n\n# Download artifact\ncurl -s \"${KUBESPHERE_API}${ARTIFACT_URL}\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" \\\n  -o \"/tmp/${ARTIFACT_NAME}\"\n\n# Verify\nls -lh \"/tmp/${ARTIFACT_NAME}\"\nfile \"/tmp/${ARTIFACT_NAME}\"\n```\n\n**Alternative: Via kubectl with exec (if artifact is in workspace):**\n```bash\n# Find the agent pod (if still running)\nAGENT_POD=$(kubectl get pods -n kubesphere-devops-worker -l jenkins/label-digest -o jsonpath='{.items[0].metadata.name}' 2>/dev/null)\n\n# Copy artifact (if pod exists)\nif [ -n \"$AGENT_POD\" ]; then\n  kubectl cp ${AGENT_POD}:/home/jenkins/agent/workspace/${PIPELINE_NAME}/${ARTIFACT_NAME} /tmp/${ARTIFACT_NAME}\nfi\n```\n\n## Managing Credentials\n\n### List Credentials\n\n```bash\ncurl -s \"${KUBESPHERE_API}/kapis/devops.kubesphere.io/v1alpha2/namespaces/${DEVOPS_PROJECT}/credentials\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" | jq '.items[].metadata.name'\n```\n\n### Create Credential\n\n**SSH Key:**\n```bash\ncurl -s -X POST \"${KUBESPHERE_API}/kapis/devops.kubesphere.io/v1alpha2/namespaces/${DEVOPS_PROJECT}/credentials\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"apiVersion\": \"v1\",\n    \"kind\": \"Secret\",\n    \"metadata\": {\n      \"name\": \"my-ssh-key\",\n      \"namespace\": \"'${DEVOPS_PROJECT}'\",\n      \"annotations\": {\n        \"kubesphere.io/creator\": \"tenant-user\",\n        \"kubesphere.io/description\": \"SSH key for Git\"\n      }\n    },\n    \"type\": \"credential.devops.kubesphere.io/ssh\",\n    \"stringData\": {\n      \"username\": \"git\",\n      \"privateKey\": \"'$(cat ~/.ssh/id_rsa | sed 's/$/\\\\n/g' | tr -d '\\n')'\"\n    }\n  }'\n```\n\n**Username/Password:**\n```bash\ncurl -s -X POST \"${KUBESPHERE_API}/kapis/devops.kubesphere.io/v1alpha2/namespaces/${DEVOPS_PROJECT}/credentials\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"apiVersion\": \"v1\",\n    \"kind\": \"Secret\",\n    \"metadata\": {\n      \"name\": \"my-basic-auth\",\n      \"namespace\": \"'${DEVOPS_PROJECT}'\"\n    },\n    \"type\": \"credential.devops.kubesphere.io/basic-auth\",\n    \"stringData\": {\n      \"username\": \"myuser\",\n      \"password\": \"mypassword\"\n    }\n  }'\n```\n\n## Multi-Cluster Operations\n\nKubeSphere supports managing DevOps resources across multiple clusters. Use the `/clusters/{cluster-name}/` prefix to forward API requests to specific member clusters.\n\n### DevOps Projects are Namespaces\n\n**Important:** In KubeSphere DevOps, a \"DevOps project\" is actually a Kubernetes namespace with the `devops.kubesphere.io/managed=true` label. The DevOpsProject CR is a wrapper resource, but when listing accessible DevOps projects for a tenant, you query **namespaces**, not DevOpsProject CRs.\n\n**Correct API for listing tenant-accessible DevOps projects:**\n```bash\n# List DevOps project namespaces (NOT devopsprojects CRs)\nGET /clusters/{cluster}/kapis/devops.kubesphere.io/v1alpha3/workspaces/{workspace}/namespaces\n```\n\nThis endpoint returns namespaces that:\n1. Have the `devops.kubesphere.io/managed=true` label\n2. Have the `kubesphere.io/workspace={workspace}` label\n3. Are accessible to the authenticated tenant\n\n### DevOps Project Naming Convention\n\nWhen users refer to DevOps projects, they may use either a **shortname** or **fullname**:\n\n| Name Type | Example | Source | Description |\n|-----------|---------|--------|-------------|\n| **Shortname** | `devopstest` | DevOpsProject CR `.metadata.generateName` | User-friendly display name |\n| **Fullname** | `devopstestc2nj7` | DevOpsProject CR `.metadata.name` | Actual namespace name |\n\n**Key Points:**\n- The **fullname** is the actual Kubernetes namespace name that you use in API calls\n- The fullname = DevOpsProject CR's `.metadata.name` = Namespace's `.metadata.name`\n- The shortname comes from `.metadata.generateName` and is used for display purposes\n\n**Resolving Ambiguity:**\nWhen a user provides a name that could match multiple projects:\n\n```bash\n# First, get all accessible DevOps project namespaces\nNAMESPACES=$(curl -s \"${KUBESPHERE_API}/clusters/member-1/kapis/devops.kubesphere.io/v1alpha3/workspaces/stone2/namespaces\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\")\n\n# Example: User says \"devopstest\" which could match:\n# - Fullname: devopstestc2nj7 (from generateName \"devopstest\")\n# - Fullname: devopstestxyz12 (from generateName \"devopstest\")\n# - Fullname: my-devopstest (different project)\n\n# Check for matches\necho \"$NAMESPACES\" | jq -r '.items[].metadata.name' | grep \"devopstest\"\n# Output might show:\n# devopstestc2nj7\n# devopstestxyz12\n\n# If multiple matches found, ask user to confirm:\n# \"Multiple DevOps projects match 'devopstest':\n#  1. devopstestc2nj7\n#  2. devopstestxyz12\n#  Which one do you want to use?\"\n```\n\n**Best Practice:**\n1. When user provides a name, check if it matches any fullname (namespace name) exactly\n2. If exact match found → use that namespace\n3. If no exact match → check if it matches any shortname (generateName prefix)\n4. If multiple matches → **ask user to confirm** before proceeding\n\n### API Path Patterns\n\n| Endpoint Type | Path Pattern | Returns | Use Case | Tenant Access |\n|--------------|--------------|---------|----------|---------------|\n| **KubeSphere API (workspace-scoped)** | `/clusters/{cluster}/kapis/devops.kubesphere.io/v1alpha3/workspaces/{workspace}/namespaces` | **Namespaces** (DevOps projects) | List DevOps project namespaces tenant can access | ✅ **Tenant accessible** |\n| **KubeSphere API (namespace-scoped)** | `/clusters/{cluster}/kapis/devops.kubesphere.io/v1alpha3/namespaces/{namespace}/pipelines` | Pipelines | Pipeline operations | ✅ **Tenant accessible** |\n| **Kubernetes API (cluster-scoped)** | `/clusters/{cluster}/apis/devops.kubesphere.io/v1alpha3/devopsprojects` | DevOpsProject CRs | Direct CR access | ❌ **Admin only (403)** |\n\n**Key Insight:** The `/kapis/` endpoints enforce workspace-level RBAC and work for tenants. The `/apis/` endpoints require cluster-scoped permissions and will return 403 for tenants. When listing DevOps projects a tenant can access, use the `/namespaces` endpoint, not `/devopsprojects`.\n\n### List DevOpsProjects Across Clusters\n\n```bash\nexport KUBESPHERE_API=\"http://kubesphere-apiserver:80\"\nexport USERNAME=\"stone-ns-admin\"\nexport PASSWORD=\"P@88w0rd\"\nexport WORKSPACE=\"stone\"\n\n# Get OAuth token\nTOKEN=$(curl -s -X POST -H 'Content-Type: application/x-www-form-urlencoded' \\\n  \"${KUBESPHERE_API}/oauth/token\" \\\n  --data-urlencode 'grant_type=password' \\\n  --data-urlencode \"username=${USERNAME}\" \\\n  --data-urlencode \"password=${PASSWORD}\" \\\n  --data-urlencode 'client_id=kubesphere' \\\n  --data-urlencode 'client_secret=kubesphere' | jq -r '.access_token')\n\n# List DevOpsProjects on Host Cluster\necho \"=== Host Cluster ===\"\ncurl -s \"${KUBESPHERE_API}/kapis/devops.kubesphere.io/v1alpha3/workspaces/${WORKSPACE}/namespaces\" \\\n  -H \"Authorization: Bearer ${TOKEN}\" | jq -r '.items[] | \"\\(.metadata.name) (\\(.metadata.creationTimestamp))\"'\n\n# List DevOpsProjects on Member-1 Cluster\necho \"=== Member-1 Cluster ===\"\ncurl -s \"${KUBESPHERE_API}/clusters/member-1/kapis/devops.kubesphere.io/v1alpha3/workspaces/${WORKSPACE}/namespaces\" \\\n  -H \"Authorization: Bearer ${TOKEN}\" | jq -r '.items[] | \"\\(.metadata.name) (\\(.metadata.creationTimestamp))\"'\n```\n\n**Example Output:**\n```\n=== Host Cluster ===\n(No output - no DevOpsProjects in workspace 'stone' on host)\n\n=== Member-1 Cluster ===\nstonedev154cht (2026-03-18T06:46:04Z)\n```\n\n### Why Tenant Can't Use /apis/ Endpoints\n\n```bash\n# ❌ This will return 403 Forbidden for tenants\ncurl -s \"${KUBESPHERE_API}/clusters/member-1/apis/devops.kubesphere.io/v1alpha3/devopsprojects\" \\\n  -H \"Authorization: Bearer ${TOKEN}\"\n\n# Output:\n# {\n#   \"kind\": \"Status\",\n#   \"apiVersion\": \"v1\",\n#   \"status\": \"Failure\",\n#   \"message\": \"devopsprojects.devops.kubesphere.io is forbidden: User \\\"stone-ns-admin\\\" cannot list resource \\\"devopsprojects\\\" in API group \\\"devops.kubesphere.io\\\" at the cluster scope\",\n#   \"reason\": \"Forbidden\",\n#   \"code\": 403\n# }\n\n# ✅ This works because /kapis/ with workspace scope enforces tenant RBAC\ncurl -s \"${KUBESPHERE_API}/clusters/member-1/kapis/devops.kubesphere.io/v1alpha3/workspaces/stone/namespaces\" \\\n  -H \"Authorization: Bearer ${TOKEN}\"\n\n# Output:\n# {\"items\":[{\"kind\":\"DevOpsProject\",\"apiVersion\":\"devops.kubesphere.io/v1alpha3\",...}]}\n```\n\n### Complete Multi-Cluster Query Script\n\n```bash\n#!/bin/bash\n\nexport KUBESPHERE_API=\"http://kubesphere-apiserver:80\"\nexport USERNAME=\"stone-ns-admin\"\nexport PASSWORD=\"P@88w0rd\"\nexport WORKSPACE=\"stone\"\n\n# Get token\nTOKEN=$(curl -s -X POST -H 'Content-Type: application/x-www-form-urlencoded' \\\n  \"${KUBESPHERE_API}/oauth/token\" \\\n  --data-urlencode 'grant_type=password' \\\n  --data-urlencode \"username=${USERNAME}\" \\\n  --data-urlencode \"password=${PASSWORD}\" \\\n  --data-urlencode 'client_id=kubesphere' \\\n  --data-urlencode 'client_secret=kubesphere' | jq -r '.access_token')\n\n# Get list of clusters (requires admin token or cluster list permission)\n# For tenants, typically hardcode the clusters they have access to\nCLUSTERS=(\"host\" \"member-1\")\n\necho \"=== DevOpsProjects in Workspace '${WORKSPACE}' Across All Clusters ===\"\nfor CLUSTER in \"${CLUSTERS[@]}\"; do\n  echo -e \"\\n## Cluster: ${CLUSTER}\"\n  \n  # Use /kapis/ endpoint with workspace scope\n  ENDPOINT=\"${KUBESPHERE_API}\"\n  if [ \"${CLUSTER}\" != \"host\" ]; then\n    ENDPOINT=\"${ENDPOINT}/clusters/${CLUSTER}\"\n  fi\n  \n  PROJECTS=$(curl -s \"${ENDPOINT}/kapis/devops.kubesphere.io/v1alpha3/workspaces/${WORKSPACE}/namespaces\" \\\n    -H \"Authorization: Bearer ${TOKEN}\")\n  \n  # Check if response contains items\n  COUNT=$(echo \"$PROJECTS\" | jq '.items | length')\n  \n  if [ \"$COUNT\" -gt 0 ]; then\n    echo \"$PROJECTS\" | jq -r '.items[] | \"  - \\(.metadata.name) (Created: \\(.metadata.creationTimestamp), Status: \\(.metadata.annotations.\"devopsproject.devops.kubesphere.io/syncstatus\" // \"N/A\"))\"'\n  else\n    echo \"  No DevOpsProjects found\"\n  fi\ndone\n```\n\n## Workspace-Scoped API Operations\n\n### Query DevOps Projects (Namespaces) by Workspace\n\nTenants can query DevOps projects (which are namespaces) within their authorized workspaces:\n\n```bash\n# List DevOps project namespaces in specific workspace\n# Note: Returns namespaces with devops.kubesphere.io/managed=true label\n# Returns empty if tenant doesn't have workspace access\ncurl -s \"${KUBESPHERE_API}/clusters/host/kapis/devops.kubesphere.io/v1alpha3/workspaces/stone/namespaces?sortBy=createTime&limit=10\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" | jq -r '.items[].metadata.name'\n\n# Example output:\n# stone-devops\n\n# Query different workspace (returns 0 items if no access)\ncurl -s \"${KUBESPHERE_API}/clusters/host/kapis/devops.kubesphere.io/v1alpha3/workspaces/demo/namespaces?sortBy=createTime&limit=10\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" | jq '.totalItems'\n\n# Example output:\n# 0\n```\n\n**Important Distinction:**\n- **DevOps Project** = A namespace with `devops.kubesphere.io/managed=true` label\n- **DevOpsProject CR** = A Kubernetes custom resource that wraps the namespace\n- To list projects a tenant can access → Use `/namespaces` endpoint\n- The `/namespaces` endpoint filters by namespace label `kubesphere.io/workspace`. If the namespace label doesn't match the workspace, it won't be returned even if the DevOpsProject CR has the correct label.\n\n### Verify Workspace Access\n\n```bash\n# Check accessible workspaces\ncurl -s \"${KUBESPHERE_API}/kapis/tenant.kubesphere.io/v1beta1/workspaces\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" | jq -r '.items[].metadata.name'\n\n# Verify specific workspace\ncurl -s \"${KUBESPHERE_API}/kapis/tenant.kubesphere.io/v1beta1/workspaces/stone\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" | jq -r '.metadata.name'\n```\n\n## GitOps Application Deployment\n\n### Create GitOps Application via API\n\nTenants can deploy applications using KubeSphere GitOps without accessing the ArgoCD namespace:\n\n```bash\n# Create GitOps Application\ncurl -s -X POST \"${KUBESPHERE_API}/kapis/gitops.kubesphere.io/v1alpha1/namespaces/demo-project/applications\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"apiVersion\": \"gitops.kubesphere.io/v1alpha1\",\n    \"kind\": \"Application\",\n    \"metadata\": {\n      \"name\": \"guestbook\",\n      \"namespace\": \"demo-project\"\n    },\n    \"spec\": {\n      \"argoApp\": {\n        \"spec\": {\n          \"project\": \"default\",\n          \"source\": {\n            \"repoURL\": \"https://github.com/stoneshi-yunify/argocd-example-apps\",\n            \"targetRevision\": \"HEAD\",\n            \"path\": \"guestbook\"\n          },\n          \"destination\": {\n            \"server\": \"https://kubernetes.default.svc\",\n            \"namespace\": \"demo-project\"\n          },\n          \"syncPolicy\": {\n            \"automated\": {\n              \"prune\": true,\n              \"selfHeal\": true\n            },\n            \"syncOptions\": [\n              \"CreateNamespace=true\"\n            ]\n          }\n        }\n      }\n    }\n  }' | jq -r '.metadata.name'\n\n# Expected output: guestbook\n```\n\n### How It Works\n\n1. **Tenant creates** `Application` (gitops.kubesphere.io/v1alpha1) in their namespace\n2. **KubeSphere automatically** creates corresponding ArgoCD Application in `argocd` namespace\n3. **ArgoCD controller** syncs the application to tenant's namespace\n4. **Tenant cannot** access ArgoCD namespace directly - all operations via KubeSphere API\n\n### Verify Application Deployment\n\n**Method 1: Check Status Labels (Recommended for Tenants)**\n\nThe Application resource includes status labels that indicate the current health and sync status:\n\n```bash\n# Get Application and check status labels\ncurl -s \"${KUBESPHERE_API}/clusters/member-1/kapis/gitops.kubesphere.io/v1alpha1/namespaces/demo-project/applications/guestbook\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" | jq -r '{\n  name: .metadata.name,\n  health: .metadata.labels[\"gitops.kubesphere.io/health-status\"],\n  sync: .metadata.labels[\"gitops.kubesphere.io/sync-status\"],\n  argocdApp: .metadata.labels[\"gitops.kubesphere.io/argocd-application\"]\n}'\n\n# Expected output when synced and healthy:\n# {\n#   \"name\": \"guestbook\",\n#   \"health\": \"Healthy\",\n#   \"sync\": \"Synced\",\n#   \"argocdApp\": \"guestbook\"\n# }\n```\n\n**Status Values:**\n\n| Label | Values | Description |\n|-------|--------|-------------|\n| `gitops.kubesphere.io/health-status` | Healthy, Progressing, Degraded, Missing, Unknown | Resource health state |\n| `gitops.kubesphere.io/sync-status` | Synced, OutOfSync | Git repository sync state |\n\n**Method 2: Check Detailed Status in .status.argoApp**\n\nFor more detailed information, parse the `.status.argoApp` field (JSON string):\n\n```bash\n# Get detailed sync and health information\ncurl -s \"${KUBESPHERE_API}/clusters/member-1/kapis/gitops.kubesphere.io/v1alpha1/namespaces/demo-project/applications/guestbook\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" | jq -r '.status.argoApp' | jq -r '{\n  syncStatus: .sync.status,\n  healthStatus: .health.status,\n  revision: .sync.revision,\n  resources: [.resources[] | {kind: .kind, name: .name, status: .status, health: .health.status}],\n  images: .summary.images\n}'\n\n# Expected output:\n# {\n#   \"syncStatus\": \"Synced\",\n#   \"healthStatus\": \"Healthy\",\n#   \"revision\": \"f946a1c393d50a460cc44944a476971fe13961f4\",\n#   \"resources\": [\n#     {\"kind\": \"Service\", \"name\": \"guestbook-ui\", \"status\": \"Synced\", \"health\": \"Healthy\"},\n#     {\"kind\": \"Deployment\", \"name\": \"guestbook-ui\", \"status\": \"Synced\", \"health\": \"Healthy\"}\n#   ],\n#   \"images\": [\"gcr.io/google-samples/gb-frontend:v5\"]\n# }\n```\n\n**Method 3: Check Operation State**\n\nFor troubleshooting sync operations:\n\n```bash\n# Get operation state and sync result\ncurl -s \"${KUBESPHERE_API}/clusters/member-1/kapis/gitops.kubesphere.io/v1alpha1/namespaces/demo-project/applications/guestbook\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" | jq -r '.status.argoApp' | jq -r '.operationState | {\n  phase: .phase,\n  message: .message,\n  startedAt: .startedAt,\n  finishedAt: .finishedAt\n}'\n\n# Expected output on success:\n# {\n#   \"phase\": \"Succeeded\",\n#   \"message\": \"successfully synced (all tasks run)\",\n#   \"startedAt\": \"2026-03-27T09:09:12Z\",\n#   \"finishedAt\": \"2026-03-27T09:09:15Z\"\n# }\n```\n\n**Understanding Destination Cluster**\n\nWhen `spec.argoApp.spec.destination.server` is `https://kubernetes.default.svc` and `destination.name` is empty or `in-cluster`, the Application deploys to the cluster specified in the API path:\n\n| API Path | Destination Cluster |\n|----------|-------------------|\n| `/kapis/gitops.kubesphere.io/v1alpha1/namespaces/{ns}/applications` | Host cluster |\n| `/clusters/member-1/kapis/gitops.kubesphere.io/v1alpha1/namespaces/{ns}/applications` | member-1 cluster |\n| `/clusters/member-2/kapis/gitops.kubesphere.io/v1alpha1/namespaces/{ns}/applications` | member-2 cluster |\n\n**Important for Tenants:**\n\nSince tenants may not have permissions to directly query the destination namespace (due to RBAC), **always verify deployment via the Application status** rather than trying to access deployed resources directly:\n\n```bash\n# ✅ CORRECT: Check Application status (tenant has permissions)\ncurl -s \"${KUBESPHERE_API}/clusters/member-1/kapis/gitops.kubesphere.io/v1alpha1/namespaces/demo-project/applications/guestbook\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" | jq -r '.metadata.labels[\"gitops.kubesphere.io/sync-status\"]'\n# Output: \"Synced\"\n\n# ❌ INCORRECT: Direct namespace access may fail for tenants\ncurl -s \"${KUBESPHERE_API}/clusters/member-1/api/v1/namespaces/demo-project/pods\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\"\n# May return 403 Forbidden\n```\n\n### Tenant Limitations (Important)\n\n| Action | Tenant Can | Notes |\n|--------|-----------|-------|\n| Create GitOps App | ✅ Yes | Via KubeSphere API |\n| Modify ArgoCD Config | ❌ No | Cannot access `argocd` namespace |\n| Add App Namespace to ArgoCD | ❌ No | Requires admin to update `application.namespaces` |\n| View ArgoCD UI | ❌ No | No direct ArgoCD access |\n| View Deployed Resources | ✅ Yes | In own namespace |\n\n## Complete Tenant Workflow\n\n### Step-by-Step: Build and Retrieve Artifacts as Tenant\n\n```bash\n#!/bin/bash\nset -e\n\n# Configuration\nexport KUBESPHERE_API=\"https://kubesphere-api.example.com\"\nexport API_TOKEN=\"<tenant-token>\"\nexport DEVOPS_PROJECT=\"demo-project\"\nexport PIPELINE_NAME=\"my-tenant-pipeline\"\n\n# 1. List available pipelines\necho \"=== Available Pipelines ===\"\ncurl -s \"${KUBESPHERE_API}/kapis/devops.kubesphere.io/v1alpha2/namespaces/${DEVOPS_PROJECT}/pipelines\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" | jq -r '.items[].metadata.name'\n\n# 2. Trigger pipeline run\necho \"=== Triggering Pipeline ===\"\nRUN_RESPONSE=$(curl -s -X POST \"${KUBESPHERE_API}/kapis/devops.kubesphere.io/v1alpha2/namespaces/${DEVOPS_PROJECT}/pipelines/${PIPELINE_NAME}/runs\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"parameters\": [{\"name\": \"BRANCH\", \"value\": \"main\"}]}')\n\nRUN_ID=$(echo $RUN_RESPONSE | jq -r '.metadata.name')\necho \"Run ID: $RUN_ID\"\n\n# 3. Wait for completion\necho \"=== Waiting for Build ===\"\nwhile true; do\n  STATUS=$(curl -s \"${KUBESPHERE_API}/kapis/devops.kubesphere.io/v1alpha2/namespaces/${DEVOPS_PROJECT}/pipelines/${PIPELINE_NAME}/runs/${RUN_ID}\" \\\n    -H \"Authorization: Bearer ${API_TOKEN}\" | jq -r '.status.phase')\n  echo \"Status: $STATUS\"\n  [[ \"$STATUS\" == \"Succeeded\" || \"$STATUS\" == \"Failed\" ]] && break\n  sleep 10\ndone\n\n# 4. Get logs\necho \"=== Console Log ===\"\ncurl -s \"${KUBESPHERE_API}/kapis/devops.kubesphere.io/v1alpha2/namespaces/${DEVOPS_PROJECT}/pipelines/${PIPELINE_NAME}/runs/${RUN_ID}/log\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" | tail -50\n\n# 5. Download artifacts\necho \"=== Downloading Artifacts ===\"\nARTIFACTS=$(curl -s \"${KUBESPHERE_API}/kapis/devops.kubesphere.io/v1alpha2/namespaces/${DEVOPS_PROJECT}/pipelines/${PIPELINE_NAME}/runs/${RUN_ID}/artifacts\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\")\n\necho \"$ARTIFACTS\" | jq -c '.[]' | while read artifact; do\n  NAME=$(echo $artifact | jq -r '.name')\n  URL=$(echo $artifact | jq -r '.url')\n  echo \"Downloading: $NAME\"\n  curl -s \"${KUBESPHERE_API}${URL}\" -H \"Authorization: Bearer ${API_TOKEN}\" -o \"/tmp/${NAME}\"\n  ls -lh \"/tmp/${NAME}\"\ndone\n\necho \"=== Done ===\"\n```\n\n## Tenant Limitations & Workarounds\n\n| Limitation | Tenant Impact | Workaround |\n|------------|---------------|------------|\n| No Jenkins token | Cannot use Jenkins API directly | Use KubeSphere `/kapis/` endpoints |\n| No kubesphere-devops-system access | Cannot view Jenkins master logs | View PipelineRun status via API |\n| No agent pod access | Cannot exec into agents | Artifacts via API or pipeline steps |\n| Limited logs | Logs may be truncated | Store logs in artifacts or external systems |\n| No webhook management | Cannot configure webhooks directly | Use KubeSphere UI or request admin |\n\n### Common Errors and Fixes\n\n**Error: 403 Forbidden**\n```bash\n# Cause: Token expired or insufficient permissions\n# Fix: Refresh token or check RBAC\n\ncurl -s \"${KUBESPHERE_API}/kapis/devops.kubesphere.io/v1alpha2/namespaces/${DEVOPS_PROJECT}/pipelines\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" -v 2>&1 | grep \"HTTP/\"\n# Should be: HTTP/2 200\n```\n\n**Error: Resource not found**\n```bash\n# Cause: Wrong namespace or resource doesn't exist\n# Fix: Verify namespace and resource names\n\nkubectl get pipelines -n ${DEVOPS_PROJECT}\nkubectl auth can-i get pipelines -n ${DEVOPS_PROJECT}\n```\n\n**Error: No logs available**\n```bash\n# Cause: Run not complete or logs not persisted\n# Fix: Wait for completion, check if run succeeded\n\nkubectl get pipelinerun ${RUN_ID} -n ${DEVOPS_PROJECT} -o jsonpath='{.status.phase}'\n```\n\n\n### Workspace API Returns Empty (Namespace Label Mismatch)\n\n**Symptom:**\n```bash\n# Query workspace API returns 0 items even though DevOpsProject exists\ncurl -s \"${KUBESPHERE_API}/clusters/host/kapis/devops.kubesphere.io/v1alpha3/workspaces/demo/namespaces\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\"\n# Output: {\"items\": null, \"totalItems\": 0}\n\n# But direct query works\ncurl -s \"${KUBESPHERE_API}/kapis/devops.kubesphere.io/v1alpha3/namespaces/demo-project/pipelines\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\"\n# Output: Returns pipelines successfully\n```\n\n**Root Cause:**\nThe workspace-scoped API filters namespaces by the label `kubesphere.io/workspace`. If the **namespace** label doesn't match the workspace, it won't be returned, even if the DevOpsProject CR has the correct label.\n\n**Check Labels:**\n```bash\n# Check DevOpsProject label (usually correct)\nkubectl get devopsproject demo-project -o jsonpath='{.metadata.labels.kubesphere\\.io/workspace}'\n# Output: demo\n\n# Check namespace label (may be empty or wrong)\nkubectl get ns demo-project -o jsonpath='{.metadata.labels.kubesphere\\.io/workspace}'\n# Output: \"\" (EMPTY - this is the problem!)\n```\n\n**Fix (Admin Required):**\n```bash\n# Update namespace label to match workspace\nkubectl label ns demo-project kubesphere.io/workspace=demo --overwrite\n\n# Verify fix\nkubectl get ns demo-project -o jsonpath='{.metadata.labels.kubesphere\\.io/workspace}'\n# Output: demo\n\n# Now workspace API returns the namespace\ncurl -s \"${KUBESPHERE_API}/clusters/host/kapis/devops.kubesphere.io/v1alpha3/workspaces/demo/namespaces\" \\\n  -H \"Authorization: Bearer ${API_TOKEN}\" | jq '.totalItems'\n# Output: 1\n```\n\n**Why This Happens:**\n- DevOpsProject CR and namespace are separate resources\n- DevOpsProject controller should sync the workspace label to the namespace\n- If the controller missed it or the label was removed, the API filtering breaks\n- Workspace-scoped APIs use namespace labels, not DevOpsProject labels\n\n## References\n\n- [KubeSphere DevOps Overview](../kubesphere-devops-overview/SKILL.md)\n- [KubeSphere DevOps Pipeline](../kubesphere-devops-pipeline/SKILL.md)\n- [DevOps API Documentation](https://docs.kubesphere.io/)\n- [RBAC in KubeSphere](https://docs.kubesphere.io/v4.1/05-access-control-and-account-management/)","tags":["kubesphere","devops","tenant","agent-skills","cloud-native","cncf","ebpf","hacktoberfest","kubernetes","llm","multi-cluster","multi-tenancy"],"capabilities":["skill","source-kubesphere","skill-kubesphere-devops-tenant","topic-agent-skills","topic-cloud-native","topic-cncf","topic-devops","topic-ebpf","topic-hacktoberfest","topic-kubernetes","topic-kubesphere","topic-llm","topic-multi-cluster","topic-multi-tenancy","topic-observability"],"categories":["kubesphere"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/kubesphere/kubesphere/kubesphere-devops-tenant","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add kubesphere/kubesphere","source_repo":"https://github.com/kubesphere/kubesphere","install_from":"skills.sh"}},"qualityScore":"0.700","qualityRationale":"deterministic score 0.70 from registry signals: · indexed on github topic:agent-skills · 16920 github stars · SKILL.md body (46,625 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-03T00:52:29.889Z","embedding":null,"createdAt":"2026-04-18T21:53:16.144Z","updatedAt":"2026-05-03T00:52:29.889Z","lastSeenAt":"2026-05-03T00:52:29.889Z","tsv":"'+0000':2238 '-03':2233,3338,4190,4197 '-1':3298,3302,3334,3525,4241 '-18':3339 '-19':2234 '-2':4247 '-20':932 '-27':4191,4198 '-50':4561 '/)':5061 '/../core/kubesphere-core/skill.md':240,348 '/.ssh/id_rsa':2697 '/apis':3170,3348 '/apis/devops.kubesphere.io/v1alpha3/devopsprojects':127,3146 '/applications':4234,4239,4245 '/argocd-application':4006 '/artifacts':1002,2467,2514,4582 '/basic-auth':1438,2743 '/bin/bash':3433,4392 '/branches':1669 '/clusters':110,125,1661,1730,1841,1872,2028,2078,2763,2838,3107,3129,3144,3559 '/clusters/host/kapis/devops.kubesphere.io/v1alpha3/workspaces/demo/namespaces':3694,4838,4993 '/clusters/host/kapis/devops.kubesphere.io/v1alpha3/workspaces/stone/namespaces':3662 '/clusters/member-1/api/v1/namespaces/demo-project/pods':4320 '/clusters/member-1/apis/devops.kubesphere.io/v1alpha3/devopsprojects':3362 '/clusters/member-1/kapis/devops.kubesphere.io/v1alpha3/namespaces/devopstestc2nj7/credentials':1399 '/clusters/member-1/kapis/devops.kubesphere.io/v1alpha3/namespaces/devopstestc2nj7/gitrepositories':1450 '/clusters/member-1/kapis/devops.kubesphere.io/v1alpha3/namespaces/devopstestc2nj7/pipelines':1509 '/clusters/member-1/kapis/devops.kubesphere.io/v1alpha3/workspaces':3308 '/clusters/member-1/kapis/devops.kubesphere.io/v1alpha3/workspaces/stone/namespaces':3413 '/clusters/member-1/kapis/devops.kubesphere.io/v1alpha3/workspaces/stone2/namespaces':2973 '/clusters/member-1/kapis/gitops.kubesphere.io/v1alpha1/namespaces':4237 '/clusters/member-1/kapis/gitops.kubesphere.io/v1alpha1/namespaces/demo-project/applications/guestbook':3982,4074,4156,4294 '/clusters/member-2/kapis/gitops.kubesphere.io/v1alpha1/namespaces':4243 '/consolelog':1880 '/creator':1537,1599,2677 '/credentials':2626,2649,2715 '/description':2683 '/dev/null':2399,2590 '/devopsprojects':3196 '/example/repo':1232 '/google-samples/gb-frontend:v5':4135 '/health-status':3996,4028 '/home/jenkins/agent/workspace':2605 '/kapis':225,226,3158,3402,3545,4648 '/kapis/devops.kubesphere.io':74 '/kapis/devops.kubesphere.io/v1alpha2':1625 '/kapis/devops.kubesphere.io/v1alpha2/namespaces':510,804,837,869,916,1097,1173,1843,1874,2129,2162,2197,2252,2286,2323,2369,2422,2458,2505,2623,2646,2712,4427,4455,4507,4545,4573,4730 '/kapis/devops.kubesphere.io/v1alpha2/search':1015 '/kapis/devops.kubesphere.io/v1alpha3/namespaces':686,767,1038,1073,1663,1732,2030,2080,3131 '/kapis/devops.kubesphere.io/v1alpha3/namespaces/demo-project/pipelines':314,4857 '/kapis/devops.kubesphere.io/v1alpha3/workspaces':112,2840,3109,3282,3566 '/kapis/gitops.kubesphere.io/v1alpha1/namespaces':4232 '/kapis/gitops.kubesphere.io/v1alpha1/namespaces/demo-project/applications':3840 '/kapis/iam.kubesphere.io/v1beta1/users/stoneshi':600 '/kapis/tenant.kubesphere.io/v1beta1/workspaces':3784 '/kapis/tenant.kubesphere.io/v1beta1/workspaces/demo':647 '/kapis/tenant.kubesphere.io/v1beta1/workspaces/stone':624,3801 '/kubesphere-devops-overview/skill.md':5051 '/kubesphere-devops-pipeline/skill.md':5055 '/log':925,2378,2431,4554 '/managed=true':2796,2853,3647,3718 '/namespaces':114,2842,3111,3193,3284,3310,3568,3738,3741 '/oauth/token':284,426,559,3237,3468 '/org/repo.git':1906 '/pipeline=$':2037 '/pipelineruns':1738,2033,2083 '/pipelines':513,689,807,840,872,919,1041,1076,1100,1176,1666,1735,1846,1877,2132,2165,2200,2255,2289,2326,2372,2425,2461,2508,3133,4430,4458,4510,4548,4576,4733 '/pipelines/stone-tenant-pipeline':770 '/runs':810,843,875,922,2135,2168,2203,2258,2292,2329,2375,2428,2464,2511,4461,4513,4551,4579 '/scan':1849 '/ssh':2691 '/stoneshi-yunify/argocd-example-apps':3874 '/stoneshi-yunify/jenkinsfiles.git':1480,1569 '/sync-status':4001,4039,4305 '/syncstatus':3601 '/tmp':2541,2547,2551,2610,4622,4626 '/type':1425 '/v1alpha1':3855 '/v1alpha1)':3910 '/v1alpha3':716,1115,1191,1465,1524,1966,3425 '/v4.1/05-access-control-and-account-management/)':5067 '/workspace':3749,4881 '/workspace=':2860 '/workspace=demo':4967 '0':484,2306,2587,3587,3685,3708,4828,4848 '04z':3342 '09':4193,4200 '1':376,534,864,1283,1312,1374,1652,1673,1831,2157,2226,2848,3031,3044,3904,3950,4416,4741,5002 '10':1675,3666,3698,4533 '12.747':2237 '12z':4194 '15110':897,2240 '15z':4201 '2':328,394,477,610,962,1298,1440,1698,1862,2398,2589,2855,3033,3059,3914,4047,4440,4740 '200':4747 '2026':2232,3337,4189,4196 '3':660,1314,1496,1711,1941,1948,2863,3067,3924,4137,4491 '4':783,3080,3934,4535 '403':121,638,988,3154,3180,3354,3398,4328,4711 '46':3341 '5':899,2276,2349,2446,4562 '50':485,2236 '7200':326,475,960 '80':3208,3440 '88w0rd':532,547,3218,3450 'access':23,26,57,97,108,145,182,203,216,306,461,463,470,482,505,591,611,617,634,907,994,1362,1367,1379,2355,2808,2826,2865,2964,3101,3121,3123,3138,3151,3190,3268,3499,3520,3657,3689,3736,3775,3778,3826,3937,4278,4311,4349,4370,4655,4669 'across':2758,3199,3531 'action':4333 'actual':2788,2908,2917 'add':4352 'admin':22,119,138,175,180,1392,1895,3152,3214,3382,3446,3506,4359,4705,4950 'admin/operator':49,135 'agent':746,1144,2567,2572,2598,2603,4667,4673 'altern':1956,2554 'alway':1257,1338,1629,4267 'ambigu':2948 'annot':1422,1534,1600,2674 'api':30,68,73,160,213,224,261,276,283,313,318,364,398,489,492,502,509,517,539,558,584,599,604,623,628,646,651,685,693,762,766,774,803,814,836,847,868,881,915,929,964,998,1014,1022,1030,1037,1045,1054,1072,1082,1096,1104,1172,1180,1398,1403,1449,1454,1508,1513,1621,1626,1632,1660,1679,1729,1744,1798,1840,1853,1871,1884,2019,2027,2043,2072,2077,2089,2103,2117,2128,2139,2161,2174,2196,2209,2251,2264,2285,2298,2322,2335,2363,2368,2382,2403,2421,2435,2457,2471,2485,2504,2518,2532,2538,2622,2630,2645,2653,2711,2719,2770,2821,2925,2972,2977,3090,3103,3125,3140,3204,3236,3281,3307,3361,3388,3412,3436,3467,3552,3613,3661,3670,3693,3702,3783,3788,3800,3805,3817,3839,3844,3945,3981,3986,4073,4078,4155,4160,4226,4228,4293,4298,4319,4324,4343,4398,4401,4426,4434,4454,4465,4506,4519,4544,4558,4572,4586,4614,4619,4644,4665,4676,4729,4737,4816,4826,4837,4842,4856,4861,4873,4985,4992,4997,5034,5040,5057 'apiserv':3207,3439 'apivers':713,1112,1188,1411,1462,1521,1963,2661,2727,3370,3422,3852 'app':4339,4353 'appli':711,1961 'applic':3811,3815,3821,3833,3857,3907,3920,3929,3947,3958,3973,4218,4272,4285 'application.namespaces':4362 'application/json':820,1110,1186,1409,1460,1519,1685,1750,1859,2659,2725,3850,4471 'application/x-www-form-urlencoded':289,431,564,3234,3465 'argoapp':3866 'argocd':3828,3919,3922,3925,3938,4345,4350,4356,4364,4369 'argocdapp':4002,4019 'artifact':999,2353,2452,2481,2488,2492,2496,2499,2524,2528,2533,2542,2548,2552,2560,2592,2608,2611,4388,4564,4567,4568,4589,4594,4598,4604,4674,4689 'ask':1271,1284,1699,3022,3084 'aspect':949 'assum':1335 'auth':1305,1428,2736,4774 'authent':80,227,229,244,349,353,367,535,594,952,2868 'author':316,515,602,626,649,691,772,812,845,879,927,1020,1043,1052,1080,1102,1178,1401,1452,1511,1677,1742,1851,1882,2041,2087,2137,2172,2207,2262,2296,2333,2380,2433,2469,2516,2536,2628,2651,2717,2975,3286,3312,3364,3415,3570,3631,3668,3700,3786,3803,3842,3984,4076,4158,4296,4322,4432,4463,4517,4556,4584,4617,4735,4840,4859,4995 'auto':1610 'auto-discov':1609 'autom':162,3887 'automat':3916 'avail':995,1000,1634,1654,1803,2411,4418,4421,4786 'base':748,1146 'bash':100,248,374,490,536,614,665,788,902,1010,1062,1090,1166,1380,1443,1502,1656,1717,1835,1867,1957,2000,2056,2120,2185,2278,2364,2416,2453,2486,2564,2618,2639,2705,2829,2960,3201,3350,3432,3633,3776,3830,3971,4063,4145,4282,4391,4713,4752,4787,4823,4907,4952 'basic':1304,1427,2735 'basic-auth':1303,1426 'bearer':317,516,603,627,650,692,773,813,846,880,928,1021,1044,1053,1081,1103,1179,1402,1453,1512,1678,1743,1852,1883,2042,2088,2138,2173,2208,2263,2297,2334,2381,2434,2470,2517,2537,2629,2652,2718,2976,3287,3313,3365,3416,3571,3669,3701,3787,3804,3843,3985,4077,4159,4297,4323,4433,4464,4518,4557,4585,4618,4736,4841,4860,4996 'behavior':951 'best':3042 'blue':830,974,1771,2109,2189 'boundari':143 'branch':1164,1207,1210,1220,1240,1251,1267,1500,1544,1547,1556,1576,1607,1612,1641,1645,1655,1689,1702,1704,1715,1719,1739,1740,1762,1763,1777,1780,1789,1818,1820,1825,1897,1911,1913,1920,1923,1929,1932,1942,1944,1987,1992,1995,4475 'break':2274,2347,4531,5036 'build':161,1151,1157,1709,1713,4385,4498 'c':4591 'call':66,2926 'can-i':4775 'cannot':56,65,3383,3936,4348,4641,4656,4670,4696 'capabl':177 'case':361,3099 'cat':708,1958,2696 'caus':4714,4753,4788,4868 'chang':1829 'check':857,1258,1910,1912,1919,1928,3002,3050,3072,3573,3777,3951,3975,4048,4138,4284,4724,4800,4905,4908,4925 'client':298,301,331,335,451,457,576,580,955,3257,3263,3488,3494 'cluster':21,111,118,126,137,181,1662,1731,1842,1873,2029,2079,2751,2760,2765,2775,2839,3108,3130,3142,3145,3174,3200,3274,3277,3299,3303,3323,3335,3393,3429,3504,3509,3517,3522,3533,3535,3537,3542,3543,3554,3560,4204,4216,4222,4231,4236,4242,4248 'cluster-admin':20,117 'cluster-nam':2764 'cluster-scop':3141,3173 'code':3397 'come':2938 'common':359,4706 'complet':242,351,519,1353,2243,2314,3426,4378,4494,4791,4799 'completiontim':2099,2310 'concis':2187,2280 'config':382,4346 'configur':380,4395,4697 'confirm':1339,3025,3087 'consol':219,904,2357,2406,4539 'contain':339,3576 'content':287,429,562,818,1108,1184,1407,1458,1517,1683,1748,1857,2657,2723,3232,3463,3848,4469 'content-typ':286,428,561,817,1107,1183,1406,1457,1516,1682,1747,1856,2656,2722,3231,3462,3847,4468 'control':3926,5014,5025 'convent':2873 'copi':2591 'core':239,255,347 'correct':101,640,2820,3771,4283,4903,4912 'correspond':3918 'could':2956,2984 'count':3578,3585 'cover':39 'cp':2602 'cr':1954,2800,2896,2906,2930,3150,3721,3768,4900,5007 'creat':661,699,1085,1138,1248,1263,1294,1299,1322,1375,1441,1497,1602,2635,3595,3813,3831,3906,3917,4337 'create/edit':189 'createnamespac':3893 'createtim':3664,3696 'creationtim':2051 'credenti':250,415,529,1233,1238,1292,1302,1317,1330,1376,1570,1828,2615,2617,2636 'credential.devops.kubesphere.io':1424,1437,2690,2742 'credential.devops.kubesphere.io/basic-auth':1436,2741 'credential.devops.kubesphere.io/ssh':2689 'credential.devops.kubesphere.io/type':1423 'criteria':1918,1927,1939 'critic':86,1256 'crs':94,2819,2836,3148 'curl':278,310,420,506,553,596,620,643,682,763,798,833,865,912,1011,1034,1069,1091,1167,1393,1444,1503,1657,1724,1836,1868,2024,2074,2125,2158,2193,2248,2282,2319,2365,2418,2454,2501,2529,2619,2640,2706,2969,3226,3278,3304,3358,3409,3457,3563,3658,3690,3780,3797,3834,3978,4070,4152,4290,4316,4423,4449,4503,4541,4569,4611,4726,4834,4853,4989 'current':390,3966 'current-us':389 'custom':3724 'd':290,565,569,572,575,579,821,1111,1187,1410,1461,1520,1751,1860,2660,2702,2726,3851,4472 'data':433,439,444,449,455,3239,3245,3250,3255,3261,3470,3476,3481,3486,3492 'data-urlencod':432,438,443,448,454,3238,3244,3249,3254,3260,3469,3475,3480,3485,3491 'date':1974 'default':3869 'degrad':4031 'demo':498,656,3863,3884,4407,4917,4924,4937,4963,4975,4982 'demo-project':497,3862,3883,4406,4916,4936,4962,4974 'deploy':3812,3820,3948,4123,4219,4269,4279,4372 'deprec':1628,2101,2104,2114,2124,2153 'descript':738,1136,1217,1490,1553,2892,4025 'destin':3879,4203,4230,4262 'destination.name':4210 'detail':245,258,354,1061,4049,4055,4065 'detect':1821 'develop':168 'devop':3,9,27,33,40,60,88,98,104,152,209,495,511,667,671,687,728,768,805,838,870,917,1039,1074,1098,1125,1174,1201,1301,1368,1664,1733,1844,1875,1977,2012,2031,2066,2081,2130,2163,2198,2253,2287,2324,2370,2393,2423,2459,2506,2580,2624,2647,2672,2713,2738,2756,2776,2783,2785,2809,2827,2831,2870,2878,2965,3027,3113,3116,3185,3616,3624,3635,3680,3711,4404,4428,4456,4508,4546,4574,4653,4731,4771,4781,4810,5049,5053,5056 'devops.kubesphere.io':715,1114,1190,1464,1523,1965,2036,2795,2852,3390,3424,3646,3717 'devops.kubesphere.io/managed=true':2794,2851,3645,3716 'devops.kubesphere.io/pipeline=$':2035 'devops.kubesphere.io/v1alpha3':714,1113,1189,1463,1522,1964,3423 'devopsproject':53,93,183,2799,2818,2835,2895,2905,2929,3147,3198,3271,3295,3327,3386,3421,3527,3606,3720,3767,4832,4899,4909,4915,5006,5013,5045 'devopsproject.devops.kubesphere.io':3600 'devopsproject.devops.kubesphere.io/syncstatus':3599 'devopsprojects.devops.kubesphere.io':3375 'devopstest':2894,2982,2990,2995,2999,3012,3030 'devopstestc2nj7':1372,1421,1475,1489,1533,2904,2987,3016,3032 'devopstestxyz12':2992,3017,3034 'differ':3000,3682 'direct':69,211,1349,3149,3940,4259,4281,4309,4368,4645,4699,4850 'discov':1239,1242,1575,1578,1611,1816 'display':2901,2945 'distinct':87,3710 'docs.kubesphere.io':5060,5066 'docs.kubesphere.io/)':5059 'docs.kubesphere.io/v4.1/05-access-control-and-account-management/)':5065 'document':5058 'doesn':3653,3754,4758,4886 'done':2277,2350,2447,3609,4534,4628,4630 'download':2480,2482,2497,2527,4563,4566,4609 'due':4264 'durat':889,896,2183,2221,2239 'durationinmilli':890,2184,2222 'e':3540,4394 'e.g':1371,1589 'echo':465,479,586,593,754,936,1156,1530,1551,2269,2340,2400,2441,2448,3005,3275,3300,3526,3539,3579,3589,3604,4420,4444,4480,4486,4495,4524,4538,4565,4588,4597,4603,4608,4629 'echo-pipelin':1529,1550 'echo/jenkinsfile':1583 'either':2883 'els':3603 'empti':1332,3650,4212,4818,4930,4944 'endpoint':1003,1760,1800,2107,2844,3093,3159,3171,3194,3349,3546,3550,3557,3558,3565,3739,3742,4649 'enforc':3160,3406 'env':1347 'eof':709,759,1959,1996 'error':4707,4710,4748,4783 'even':3764,4830,4896 'exact':3058,3061,3070 'exampl':521,1886,2223,2890,2979,3320,3676,3706 'except':1790 'exchang':249,414 'exec':2558,4671 'exist':1291,2595,4760,4833 'expect':933,3898,4007,4103,4176 'expir':324,473,4716 'expiri':959 'export':259,263,268,275,400,404,409,491,494,500,537,541,544,583,666,789,861,1063,1381,1386,1718,2154,2487,2491,3202,3209,3215,3219,3434,3441,3447,3451,4396,4400,4403,4409 'extern':4691 'extract':460 'f':712,1962 'f946a1c393d50a460cc44944a476971fe13961f4':4110 'face':171 'fail':2346,4313,4530 'failur':3373 'fals':1244,1580 'featur':1922 'feature-branch':1921 'fetch':1863,1907 'fi':2613,3561,3608 'field':981,1593,2192,4060 'file':2550 'filter':1670,3743,4874,5035 'find':948,2565 'finish':893,945,1943,1950,2228,2273,2439 'finishedat':4174,4175,4195 'first':1261,1343,2961 'fix':4709,4720,4761,4796,4949,4970 'forbidden':639,658,989,3355,3377,3396,4329,4712 'forc':1809 'format':832,973,1773,2111,2191 'forward':2769 'found':1916,1925,1935,3021,3063,3607,4751 'friend':2900 'full':215 'fullnam':2887,2903,2914,2928,2986,2991,2996,3055 'gcr.io':4134 'gcr.io/google-samples/gb-frontend:v5':4133 'generatenam':2989,2994,3078 'get':109,124,273,362,548,900,903,1059,2009,2053,2061,2149,2186,2279,2356,2388,2495,2575,2837,2962,3222,3454,3501,3972,4064,4146,4536,4768,4778,4805,4914,4934,4972 'ghp':1384 'git':1226,1227,1237,1431,1563,1564,1899,2687,2694,4042 'git_source.credential':1319 'github':1308,1346,1357,1360,1378,1382,1418,1433,1482,1486,1573,1590 'github-token':1417,1485,1572 'github.com':1231,1479,1568,1905,3873 'github.com/example/repo':1230 'github.com/org/repo.git':1904 'github.com/stoneshi-yunify/argocd-example-apps':3872 'github.com/stoneshi-yunify/jenkinsfiles.git':1478,1567 'gitop':3810,3814,3824,3832,4338 'gitops.kubesphere.io':3854,3909,3995,4000,4005,4027,4038,4304 'gitops.kubesphere.io/argocd-application':4004 'gitops.kubesphere.io/health-status':3994,4026 'gitops.kubesphere.io/sync-status':3999,4037,4303 'gitops.kubesphere.io/v1alpha1':3853 'gitops.kubesphere.io/v1alpha1)':3908 'gitrepositori':1442,1467,1586 'grant':291,435,566,3241,3472 'grep':2437,3011,4742 'group':3389 'gt':3586 'guestbook':3860,3878,3900,4014,4020,4116,4126 'guestbook-ui':4115,4125 'guid':38 'h':285,315,427,514,560,601,625,648,690,771,811,816,844,878,926,1019,1042,1051,1079,1101,1106,1177,1182,1400,1405,1451,1456,1510,1515,1676,1681,1741,1746,1850,1855,1881,2040,2086,2136,2171,2206,2261,2295,2332,2379,2432,2468,2515,2535,2627,2650,2655,2716,2721,2974,3230,3285,3311,3363,3414,3461,3569,3667,3699,3785,3802,3841,3846,3983,4075,4157,4295,4321,4431,4462,4467,4516,4555,4583,4616,4734,4839,4858,4994 'happen':5005 'hardcod':3515 'head':3876 'health':3967,3992,4015,4035,4068,4099,4120,4130 'health.status':4088,4100 'healthi':4012,4016,4029,4108,4121,4131 'healthstatus':4087,4107 'hello':755,937,941 'host':3273,3276,3322,3332,3523,3555,4235 'hour':329,478,963 'http':4743 'http/2':4746 'id':299,332,452,577,825,851,852,863,877,924,1234,1320,1331,1571,2143,2144,2156,2170,2177,2178,2205,2213,2214,2225,2260,2294,2331,2377,2391,2430,2466,2513,3258,3489,4479,4488,4490,4515,4553,4581,4808 'id/client_secret':956 'imag':4101,4132 'immedi':1810,2412 'impact':4636 'import':2780,3709,4249,4332 'in-clust':4214 'includ':355,935,3960 'incorrect':4308 'index':1826,1898,1945,1946 'indic':3964 'inform':4056,4069 'insight':3156 'insuffici':4718 'io/workspace':4922,4942,4980 'isol':642,987 'issu':1822 'item':697,850,1049,1057,1688,2046,2142,2586,2633,3009,3291,3317,3419,3577,3582,3593,3674,3686,3792,4438,4829,4845 'jenkin':62,67,84,147,204,212,218,235,373,909,4639,4643,4658 'jenkins/label-digest':2583 'jenkinsfil':744,1141,1247,1494,1915,1924,1933 'jq':304,468,589,606,630,695,776,822,849,883,1047,1056,1084,1686,1753,2045,2091,2141,2176,2211,2266,2300,2337,2473,2520,2632,3007,3266,3289,3315,3497,3581,3591,3672,3704,3790,3807,3895,3988,4080,4083,4162,4165,4300,4436,4483,4521,4590,4599,4605,4999 'json':976,4061 'jsonpath':386,2069,2396,2585,4813,4920,4940,4978 'key':320,947,1584,1756,2638,2670,2685,2911,3155 'kind':717,1116,1192,1413,1466,1525,1967,2663,2729,3368,3420,3856,4093,4094,4112,4122 'kubeconfig':378 'kubectl':381,702,710,1955,1960,2002,2008,2058,2060,2386,2387,2556,2574,2601,4767,4773,4804,4913,4933,4959,4971 'kubernet':978,1767,2005,2022,2790,2918,3139,3723 'kubernetes.default.svc':3881,4208 'kubespher':2,8,29,32,59,72,79,151,159,208,223,231,238,260,282,300,303,312,333,337,346,363,369,396,401,424,453,459,501,508,538,557,578,582,598,622,645,684,765,802,835,867,914,957,997,1013,1036,1071,1095,1171,1397,1448,1507,1659,1728,1839,1870,2026,2076,2127,2160,2195,2250,2284,2321,2362,2367,2420,2456,2484,2503,2531,2579,2621,2644,2710,2753,2782,2971,3102,3124,3203,3206,3235,3259,3265,3280,3306,3360,3411,3435,3438,3466,3490,3496,3551,3660,3692,3782,3799,3823,3838,3915,3944,3980,4072,4154,4292,4318,4342,4397,4425,4453,4505,4543,4571,4613,4647,4652,4701,4728,4836,4855,4991,5048,5052,5064 'kubesphere-api.example.com':262,403,503,4399 'kubesphere-apiserv':3205,3437 'kubesphere-apiserver.kubesphere-system.svc:80':540 'kubesphere-cor':237,345 'kubesphere-devops-system':58,150,207,4651 'kubesphere-devops-ten':1 'kubesphere-devops-work':2578 'kubesphere.io':1536,1598,2676,2682,2859,3748,4880,4966 'kubesphere.io/creator':1535,1597,2675 'kubesphere.io/description':2681 'kubesphere.io/workspace':3747,4879 'kubesphere.io/workspace=':2858 'kubesphere.io/workspace=demo':4965 'l':2582 'label':747,1145,2797,2854,2862,3648,3719,3746,3753,3772,3953,3962,3977,4023,4820,4878,4885,4904,4906,4910,4927,4955,4960,5019,5030,5043,5046 'labelselector':2034 'latest':1691 'latestrun.id':1692 'latestrun.result':1695 'length':3583 'level':3163 'lh':2546,4625 'like':1707 'limit':17,1674,3665,3697,4331,4632,4634,4680 'list':96,102,663,677,828,1006,1025,1653,1997,2121,2451,2616,2807,2823,2830,3115,3184,3197,3270,3294,3384,3502,3510,3634,3731,4417 'log':901,905,993,1865,2351,2358,2401,2407,2444,2449,4537,4540,4660,4681,4682,4687,4785,4793 'ls':1901,2545,4624 'ls-remot':1900 'main':1720,1914,1986,4477 'manag':2614,2755,4695 'manual':1823 'master':4659 'match':2957,2985,3004,3020,3029,3053,3062,3071,3075,3083,3756,4888,4957 'may':2408,2881,4254,4312,4326,4683,4928 'meet':1938 'member':2774,3297,3301,3333,3524,4240,4246 'messag':654,3374,4170,4171,4182 'met':1917,1926 'metadata':719,1118,1194,1415,1468,1527,1969,2665,2731,3858 'metadata.annotations':3598 'metadata.creationtimestamp':2017,2052,3293,3319,3596 'metadata.generatename':2897,2940 'metadata.labels':3993,3998,4003,4302 'metadata.labels.kubesphere':4921,4941,4979 'metadata.name':608,632,698,779,1050,1058,1755,2048,2094,2588,2634,2907,2932,2935,3010,3292,3318,3594,3675,3793,3809,3897,3991,4439,4485 'method':375,393,2360,3949,4046,4136 'might':3014 'mismatch':4821 'miss':4032,5026 'modifi':4344 'monitor':786 'multi':1163,1206,1209,1219,1250,1266,1499,1543,1546,1555,1606,1640,1644,1776,1788,1991,2750,3428 'multi-branch':1162,1218,1249,1265,1498,1554,1605,1639,1643,1775,1787,1990 'multi-branch-pipelin':1205,1542 'multi-clust':2749,3427 'multibranch':1198,1215 'multipl':2759,2958,3019,3026,3082 'must':70,672,1270,1595 'my-basic-auth':2733 'my-devopstest':2997 'my-git-credenti':1235 'my-multibranch-pipelin':1196,1213 'my-pipelin':1066 'my-private-repo':1470 'my-run':1971 'my-ssh-key':2667 'my-tenant-pipelin':1120,1132,4412 'mypassword':2748 'myuser':2746 'n':1143,1147,1149,1152,1154,1158,1159,1160,1161,2011,2065,2392,2577,2597,2703,3541,4770,4780,4809 'n/a':1693,1696,3602 'n/g':2700 'name':388,720,733,778,791,809,842,874,921,1065,1078,1119,1131,1195,1212,1388,1416,1469,1484,1528,1539,1549,1668,1690,1737,1848,1879,1970,1981,1983,1988,2039,2047,2064,2085,2093,2134,2167,2202,2257,2291,2328,2374,2427,2463,2474,2475,2489,2510,2523,2525,2543,2549,2553,2607,2609,2612,2666,2732,2766,2872,2888,2902,2910,2920,2954,3049,3057,3859,3990,4013,4095,4096,4114,4124,4411,4460,4474,4512,4550,4578,4596,4601,4610,4623,4627,4766 'namespac':13,44,54,91,103,142,165,179,185,188,193,195,200,202,681,706,725,986,1028,1124,1200,1370,1420,1474,1488,1532,1976,2671,2737,2779,2791,2816,2833,2846,2909,2919,2933,2967,2968,3006,3056,3066,3112,3118,3127,3132,3618,3628,3637,3643,3714,3729,3745,3752,3829,3861,3882,3913,3923,3933,3939,4263,4310,4351,4354,4377,4755,4763,4819,4875,4884,4926,4954,4988,5009,5022,5042 'namespace-scop':12,43,164,3126 'need':154,911 'never':1334,1344 'new':1296,1817 'nodeport':222 'note':2405,3641,4336 'notic':1623 'ns':1391,1894,3213,3381,3445,4233,4238,4244,4935,4961,4973 'null':4846 'o':385,2068,2395,2540,2584,4621,4812,4919,4939,4977 'oauth':81,233,243,252,322,352,371,397,549,953,3223 'obtain':481 'ocean':831,975,1772,2110,2190 'old':1931 'old-branch':1930 'one':1297,3036 'oper':7,35,41,77,131,1005,2752,3136,3614,3942,4139,4144,4147 'operationst':4167 'origin':1671,1909 'outofsync':4041 'output':653,891,934,1888,2224,3013,3321,3325,3367,3418,3677,3707,3899,4008,4104,4177,4306,4844,4863,4923,4943,4981,5001 'overview':36,5050 'overwrit':4968 'p':531,546,3217,3449 'page':1672 'paramet':1716,1752,1765,1781,4473 'pars':4057 'password':269,272,293,296,297,410,413,437,446,447,545,568,573,574,1432,2747,3216,3243,3252,3253,3448,3474,3483,3484 'pat':1309,1364,1383,1434 'path':1246,1582,2476,2477,2493,3091,3095,3877,4227,4229 'pattern':3092,3096 'permiss':18,50,176,343,707,3176,3511,4257,4289,4719 'persist':4795 'person':1361 'phase':2049,2095,4168,4169,4180 'pipelin':157,190,664,678,700,718,724,731,732,737,740,745,758,790,795,808,841,873,920,940,944,968,1004,1007,1018,1033,1060,1064,1068,1077,1086,1089,1117,1123,1129,1130,1135,1137,1142,1165,1193,1199,1208,1211,1216,1221,1252,1268,1324,1351,1501,1526,1531,1545,1548,1552,1557,1594,1608,1616,1637,1646,1667,1736,1778,1847,1878,1982,1993,1998,2038,2133,2166,2201,2256,2290,2327,2373,2426,2462,2509,2606,3134,3135,4410,4415,4419,4422,4442,4446,4459,4511,4549,4577,4678,4769,4779,4865,5054 'pipelineref':1980 'pipelinerun':197,1768,1953,1968,2006,2010,2062,2389,4662,4806 'pod':2568,2573,2576,2594,2599,2604,4668 'point':321,1585,1757,2912 'poll':2413 'post':281,423,556,801,1094,1170,1396,1447,1506,1727,1838,2643,2709,3229,3460,3837,4452 'practic':3043 'prefer':1630,2003,2059 'prefix':2767,3079 'prerequisit':1359 'privat':1254,1277,1281,1356,1472,1491,1559 'privatekey':2695 'problem':4948 'procedur':1650 'proceed':3089 'process':1940 'progress':4030 'project':89,99,105,134,496,499,512,668,688,769,806,839,871,918,1040,1075,1099,1126,1175,1202,1369,1665,1734,1845,1876,1978,2013,2032,2067,2082,2131,2164,2199,2254,2288,2325,2371,2394,2424,2460,2507,2625,2648,2673,2714,2739,2777,2786,2810,2828,2832,2871,2879,2959,2966,3001,3028,3114,3117,3186,3562,3580,3590,3617,3625,3636,3712,3732,3864,3868,3885,4405,4408,4429,4457,4509,4547,4575,4732,4772,4782,4811,4918,4938,4964,4976 'provid':1481,2952,3047 'prune':1908,3888 'public':1327 'purpos':2946 'q':1016,2438 'queri':1764,2815,3430,3615,3623,3681,4260,4824,4851 'queued/running/finished':983 'quick':246 'r':305,469,590,607,631,696,777,823,884,1048,1687,1754,2092,2212,2267,2301,2338,2521,3008,3267,3290,3316,3498,3592,3673,3791,3808,3896,3989,4081,4084,4163,4166,4301,4437,4484,4522,4600,4606 'rather':4274 'raw':384 'rbac':342,3164,3408,4266,4725,5062 're':1813 're-scan':1812 'read':4593 'readi':2415,2450 'reason':2307,3395 'recommend':399,3954 'refer':247,1315,2876,5047 'refnam':1985 'refresh':357,4721 'reftyp':1994 'regular':1088 'remot':1902 'remov':5032 'repo':1282,1328,1366,1473,1560 'repositori':1255,1259,1278,1336,1358,1492,1615,1785,1794,1811,4043 'repourl':3871 'request':2771,4704 'requir':116,1587,1783,3172,3505,4358,4951 'resolv':2947 'resourc':613,979,1769,2007,2023,2757,2804,3385,3725,3959,4034,4091,4092,4111,4280,4373,4749,4757,4765,5012 'respons':419,467,552,588,972,3575,4448,4482 'result':855,856,887,888,894,984,2147,2148,2181,2182,2217,2218,2229,2304,4151 'retriev':4387 'return':120,618,637,1766,2004,2021,2108,2845,3097,3179,3353,3642,3649,3684,3763,4327,4817,4827,4864,4895,4986 'revis':4089,4109 'root':4867 'rule':1793 'run':787,797,829,859,862,876,923,971,1617,1638,1973,1999,2054,2063,2084,2122,2150,2155,2169,2204,2259,2293,2330,2376,2390,2429,2465,2512,2571,4187,4443,4447,4478,4481,4487,4489,4514,4552,4580,4789,4802,4807 'runid':824 'say':2981 'scan':1786,1795,1814,1833,1864,1887 'scm':1984 'scope':14,45,166,3106,3128,3143,3175,3394,3405,3549,3612,4872,5039 'script':1245,1581,3431 'sec':1949 'second':327,476,961 'secret':63,148,205,302,336,458,581,1414,1483,2664,2730,3264,3495 'sed':2698 'see':236,254,344,1310 'select':1723,2522 'selfheal':3890 'separ':5011 'server':3880 'servic':2490,2494,4113 'set':1329,4393 'sh':753,1155 'shortnam':2885,2893,2937,3077 'show':3015 'shown':2118 'sinc':4252 'size':2478,2479 'skill':256 'skill-kubesphere-devops-tenant' 'sleep':2275,2348,2445,4532 'sort':2015 'sort-bi':2014 'sortbi':3663,3695 'sourc':1224,1228,1561,1565,2891,3870 'source-kubesphere' 'spec':729,1127,1203,1352,1476,1540,1979,3865,3867 'spec.argoapp.spec.destination.server':4206 'spec.provider':1588 'spec.secret':1592 'spec.type':781 'specif':858,1027,2773,3639,3795 'specifi':4223 'ssh':2637,2669,2684 'stage':749,750,1148,1150 'start':1889,1896 'startedat':4172,4173,4188 'starttim':2097,2219,2220,2231,2308 'state':826,827,853,854,885,886,892,982,2145,2146,2179,2180,2215,2216,2227,2268,2270,2302,4036,4045,4140,4148 'status':860,980,1694,2055,2151,2188,2247,2271,2272,2281,2318,2341,2342,2343,2345,3369,3372,3597,3952,3961,3970,3976,4021,4050,4097,4098,4118,4128,4273,4286,4502,4525,4526,4527,4529,4663 'status.argoapp':4052,4059,4082,4164 'status.completiontime':2100,2311 'status.conditions':2305 'status.log':2397 'status.phase':2050,2070,2096,2303,2339,4523,4814 'status.starttime':2098,2309 'step':533,609,659,752,782,898,1153,1311,1373,1439,1495,1649,1651,1697,1710,1830,1861,4382,4384,4679 'step-by-step':4381 'still':2570 'stone':619,670,675,722,727,735,793,1390,1893,3212,3221,3330,3380,3444,3453,3679 'stone-devop':669,726,3678 'stone-ns-admin':1389,1892,3211,3379,3443 'stone-tenant-pipelin':721,734,792 'stonedev154cht':3336 'stoneshi':530,543 'store':4686 'string':1333,4062 'stringdata':1429,2692,2744 'succeed':2344,4181,4528,4803 'success':895,946,1951,2230,4179,4183,4866 'success/failure':985 'summary.images':4102 'support':2754 'symptom':4822 'symref':1903 'sync':3927,3969,3997,4010,4017,4018,4040,4044,4066,4106,4119,4129,4143,4150,4184,4307,5016 'sync.revision':4090 'sync.status':4086 'syncopt':3892 'syncpolici':3886 'syncstatus':4085,4105 'system':61,153,210,4654,4692 't02':2235 't06':3340 't09':4192,4199 'tag':1243,1579 'tail':931,4560 'targetrevis':3875 'task':4186 'tenant':4,15,34,46,106,123,141,170,173,178,228,266,271,366,407,412,528,641,680,704,723,736,742,757,794,906,939,943,950,1008,1087,1122,1134,1140,1223,1387,1538,1604,1619,2354,2359,2679,2813,2825,2869,3100,3119,3122,3137,3168,3182,3188,3344,3357,3407,3513,3621,3652,3734,3818,3905,3931,3935,3956,4251,4253,4287,4315,4330,4334,4379,4390,4414,4631,4635 'tenant-access':2824 'tenant-fac':169 'tenant-password':270,411 'tenant-us':265,406,2678 'test':739,751 'though':4831 'three':1648 'three-step':1647 'token':64,82,85,253,274,277,307,309,319,323,338,356,365,417,418,462,464,466,471,472,480,483,487,493,518,550,551,585,587,592,605,629,652,694,775,815,848,882,910,930,958,1023,1046,1055,1083,1105,1181,1363,1404,1419,1455,1487,1514,1574,1680,1745,1854,1885,2044,2090,2140,2175,2210,2265,2299,2336,2383,2436,2472,2519,2539,2631,2654,2720,2978,3224,3225,3269,3288,3314,3366,3417,3455,3456,3500,3507,3572,3671,3703,3789,3806,3845,3987,4079,4161,4299,4325,4402,4435,4466,4520,4559,4587,4620,4640,4715,4722,4738,4843,4862,4998 'took':1947 'tool':172 'topic-agent-skills' 'topic-cloud-native' 'topic-cncf' 'topic-devops' 'topic-ebpf' 'topic-hacktoberfest' 'topic-kubernetes' 'topic-kubesphere' 'topic-llm' 'topic-multi-cluster' 'topic-multi-tenancy' 'topic-observability' 'totalitem':3705,4847,5000 'tr':2701 'tri':633,4276 'trigger':156,784,796,1635,1712,1784,1824,1832,4441,4445 'troubleshoot':1819,4142 'true':1241,1577,2245,2316,3889,3891,3894,4500 'truncat':4685 'type':288,292,430,436,563,567,730,780,819,1017,1109,1128,1185,1204,1225,1260,1306,1337,1408,1435,1459,1518,1541,1562,1684,1749,1858,2658,2688,2724,2740,2889,3094,3233,3242,3464,3473,3849,4470 'typic':3514 'ui':4117,4127,4365,4702 'understand':4202 'unknown':4033 'updat':4361,4953 'url':402,425,1229,1477,1566,2498,2500,2526,2534,4602,4607,4615 'urlencod':434,440,445,450,456,3240,3246,3251,3256,3262,3471,3477,3482,3487,3493 'use':5,71,78,130,308,330,360,377,486,527,1289,1345,1758,1796,1808,2115,2761,2882,2923,2943,3041,3064,3098,3191,3347,3544,3737,3822,4642,4646,4700,5041 'user':167,267,340,387,391,408,1273,1342,1700,1721,1891,2680,2875,2899,2951,2980,3023,3046,3085,3378 'user-friend':2898 'user.token':392 'usernam':264,294,295,405,441,442,542,570,571,1430,2693,2745,3210,3247,3248,3442,3478,3479 'username/password':2704 'usual':4911 'v':4739 'v1':1412,2662,2728,3371 'v1alpha2':969,1797,1834,1866,2102,2106,2123,2152 'v1alpha3':966,1031,1631,1759,1792,1805,2020,2073,2116 'valu':4022,4024,4476 'var':1348 'verif':743 'verifi':504,525,615,760,2544,3773,3794,3946,4268,4762,4969 'version':965,1622 'via':158,221,230,368,395,701,761,996,1001,1029,1952,2001,2018,2057,2071,2361,2402,2483,2555,3816,3943,4270,4341,4664,4675 'view':196,217,383,1009,4363,4371,4657,4661 'vs':174 'wait':2442,4492,4496,4797 'want':1287,3039 'watch':2241,2312 'way':1620 'webhook':4694,4698 'within':51,140,3629 'without':19,3825 'won':3760,4892 'work':139,520,3166,3400,3903,4852 'workaround':4633,4637 'worker':2581 'workflow':526,1354,4380 'workspac':113,612,616,636,676,992,2563,2841,2861,3105,3110,3162,3220,3283,3309,3329,3404,3452,3529,3530,3548,3567,3611,3620,3632,3640,3656,3683,3758,3774,3779,3796,4815,4825,4871,4890,4958,4984,5018,5038 'workspace-level':3161 'workspace-scop':3104,3610,4870,5037 'workspaces.tenant.kubesphere.io':655 'would':1705 'wrap':3727 'wrapper':2803 'wrong':115,4754,4932 'x':280,422,555,800,1093,1169,1395,1446,1505,1726,1837,2642,2708,3228,3459,3836,4451 'xxxxxxxxxxxxxxxxxxxx':1385 'yes':1280,4340,4374","prices":[{"id":"8ae9e4cc-d5ec-44c2-8331-d315652d4dda","listingId":"2bcc7235-c7ad-4e56-9a31-c8f2e3277a2a","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"kubesphere","category":"kubesphere","install_from":"skills.sh"},"createdAt":"2026-04-18T21:53:16.144Z"}],"sources":[{"listingId":"2bcc7235-c7ad-4e56-9a31-c8f2e3277a2a","source":"github","sourceId":"kubesphere/kubesphere/kubesphere-devops-tenant","sourceUrl":"https://github.com/kubesphere/kubesphere/tree/master/skills/kubesphere-devops-tenant","isPrimary":false,"firstSeenAt":"2026-04-18T21:53:16.144Z","lastSeenAt":"2026-05-03T00:52:29.889Z"}],"details":{"listingId":"2bcc7235-c7ad-4e56-9a31-c8f2e3277a2a","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"kubesphere","slug":"kubesphere-devops-tenant","github":{"repo":"kubesphere/kubesphere","stars":16920,"topics":["agent-skills","ai","cloud-native","cncf","devops","ebpf","hacktoberfest","kubernetes","kubesphere","llm","multi-cluster","multi-tenancy","observability","servicemesh","skills","skills-sh","skillsmp"],"license":"other","html_url":"https://github.com/kubesphere/kubesphere","pushed_at":"2026-04-27T06:10:27Z","description":"The container platform tailored for Kubernetes multi-cloud, datacenter, and edge management ⎈ 🖥 ☁️","skill_md_sha":"06882d8b606637480fdd5a5ae5d1d7e85c735c27","skill_md_path":"skills/kubesphere-devops-tenant/SKILL.md","default_branch":"master","skill_tree_url":"https://github.com/kubesphere/kubesphere/tree/master/skills/kubesphere-devops-tenant"},"layout":"multi","source":"github","category":"kubesphere","frontmatter":{"name":"kubesphere-devops-tenant","description":"Use when operating KubeSphere DevOps as a namespace-scoped tenant with limited permissions, without cluster-admin access, or when accessing DevOps through KubeSphere APIs only"},"skills_sh_url":"https://skills.sh/kubesphere/kubesphere/kubesphere-devops-tenant"},"updatedAt":"2026-05-03T00:52:29.889Z"}}