Awesome-omni-skill dot-ai-port-setup
Set up Port integrations to sync Kubernetes resources and GitHub Actions to Port.io
git clone https://github.com/diegosouzapw/awesome-omni-skill
T=$(mktemp -d) && git clone --depth=1 https://github.com/diegosouzapw/awesome-omni-skill "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/devops/dot-ai-port-setup" ~/.claude/skills/diegosouzapw-awesome-omni-skill-dot-ai-port-setup && rm -rf "$T"
skills/devops/dot-ai-port-setup/SKILL.mdSetup Port Integrations
Set up Port integrations to sync Kubernetes resources and GitHub Actions to Port.io.
Prerequisites
Check the following and instruct the user to install/configure if missing:
- kubectl - installed and configured with cluster access
- helm - installed (for checking chart versions)
- gh - GitHub CLI installed and authenticated
- Environment variables set:
PORT_CLIENT_IDPORT_CLIENT_SECRET
General Guidelines
- Always check latest versions of third-party tools (Helm charts, GitHub Actions, etc.) before creating manifests. Use
or check the official documentation.helm search repo - Consult Port MCP tools when in doubt - use them to explore existing blueprints, entities, actions, and integrations.
- Validate each step before moving to the next - verify resources are created, synced, and working as expected.
- User actions vs automated: Some steps require user action (marked with "User action required") - present these as instructions, then STOP and wait for user confirmation before proceeding to the next step.
Step 0: Discover Environment
Before starting, discover what tools are available and gather configuration:
- GitOps Tool: Check for ArgoCD (
namespace) or Flux (argocd
namespace)flux-system - ESO: Check for External Secrets Operator CRD and available ClusterSecretStores
- Manifest directory: Ask the user where manifests should be stored (e.g.,
,apps/
,manifests/
)k8s/
| GitOps Tool | Deployment Method | Self-Service Actions |
|---|---|---|
| ArgoCD | ArgoCD Application manifests in Git | Commit YAML to Git → ArgoCD syncs |
| Flux | Flux HelmRelease/Kustomization in Git | Commit YAML to Git → Flux syncs |
| Neither | Manifests in Git + | Commit YAML to Git → |
| ESO Status | Secrets Method |
|---|---|
| Installed with ClusterSecretStore | Use ExternalSecret to pull from secret manager |
| Not installed | Create Secret directly with |
Note: Always store manifests in Git for auditability, regardless of GitOps availability.
GitOps Workflow Rules
IMPORTANT: When ArgoCD or Flux is detected, NEVER run
on application manifests.kubectl apply
Instead, follow this workflow:
- Write manifests to Git - Create the YAML files in the manifest directory
- Commit and push - The GitOps tool will detect changes and sync automatically
- Verify sync status - Use
(ArgoCD) orkubectl get applications -n argocd
(Flux)flux get all
For GitOps resources (ArgoCD Applications, Flux Kustomizations/HelmReleases):
- Discover the deployment pattern by examining existing resources in the cluster
- Add new manifests to the appropriate watched directory so GitOps syncs them automatically
For Secrets without ESO:
- Use
directly (secrets cannot be stored unencrypted in Git)kubectl create secret
Part 1: Kubernetes Exporter
Step 1: Create Port Credentials Secret
Create a Secret named
port-credentials in the port-k8s-exporter namespace with keys PORT_CLIENT_ID and PORT_CLIENT_SECRET.
- With ESO: Create an ExternalSecret referencing the available ClusterSecretStore
- Without ESO: Create the Secret directly with
kubectl create secret
Step 2: Deploy the K8s Exporter
Deploy the
port-k8s-exporter Helm chart from https://port-labs.github.io/helm-charts.
Key Helm values:
andsecret.useExistingSecret: truesecret.name: port-credentials
(forces use of configMap config)overwriteConfigurationOnRestart: true
andstateKey
set to cluster identifierextraEnv[].CLUSTER_NAME
with resource mappings (see Step 4)configMap.config
Deployment method based on discovery:
- ArgoCD: Create ArgoCD Application manifest
- Flux: Create HelmRepository + HelmRelease manifests
- Neither: Run
then commit values to Githelm install
Step 3: Create Blueprints in Port
Default blueprints (always created by the exporter):
(Port concept, not a K8s resource)cluster
(from namespaces)namespace
(from deployments, daemonsets, statefulsets)workload
Discover and recommend:
- Run
to list all available resourceskubectl api-resources - Exclude resources already covered by defaults (namespaces, deployments, daemonsets, statefulsets)
- Present findings to the user with recommendations
- Let user select which additional resources to track
Create selected blueprints using Port MCP tools. All blueprints should have:
- Relation to
blueprintnamespace
propertycreationTimestamp
Step 4: Configure Resource Mappings
In the Helm values
configMap.config, define mappings for the resources selected in Step 3.
For nested resources (arrays inside a resource spec), use
itemsToParse:
- kind: your.api/v1/yourresource selector: query: "true" port: itemsToParse: .spec.items entity: mappings: - identifier: .item.name + "-" + .metadata.namespace + "-" + env.CLUSTER_NAME blueprint: '"child-blueprint"' properties: name: .item.name relations: Parent: .metadata.name + "-" + .metadata.namespace + "-" + env.CLUSTER_NAME
Step 5: Configure Blueprint Relations
Analyze exported resources and establish relations:
- Examine ownerReferences to link child → parent resources
- Use selector labels to connect Services → Workloads
- Link Ingress/HTTPRoute → Services via backend references
For each relation:
- Add the relation to the blueprint in Port
- Add the corresponding JQ mapping in the exporter config
Part 2: GitHub Integration
Sync GitHub workflows, workflow runs, and pull requests to Port.
Step 1: Install Port's GitHub App (User action required)
- Go to Port's Data Sources: https://app.port.io/settings/data-sources
- Click "+ Data source" → select "GitHub"
- Install the GitHub App on your account/organization
- Select repositories to sync
- Ensure permissions for: actions, checks, pull requests, repository metadata
Step 2: Create GitHub Blueprints
Create blueprints for
githubWorkflow, githubWorkflowRun, and githubPullRequest (if not exists) using Port MCP tools. Inspect integration kinds to determine appropriate properties.
Step 3: Configure GitHub Integration Mapping
Use Port REST API to update the integration config with mappings for
pull-request, workflow, and workflow-run kinds.
Step 4: Trigger Integration Resync
After creating blueprints, trigger a resync so the integration populates them with data. Use the Port API:
# Get access token curl -s -X POST 'https://api.getport.io/v1/auth/access_token' \ -H 'Content-Type: application/json' \ -d '{"clientId": "'"$PORT_CLIENT_ID"'", "clientSecret": "'"$PORT_CLIENT_SECRET"'"}' \ | jq -r '.accessToken' > ./port_access_token.txt # Trigger resync (replace INTEGRATION_ID with actual ID) curl -s -X PATCH 'https://api.getport.io/v1/integration/INTEGRATION_ID' \ -H "Authorization: Bearer $(cat ./port_access_token.txt)" \ -H 'Content-Type: application/json' \ -d '{}' # Cleanup rm -f ./port_access_token.txt
Get the integration ID from
mcp__port-vscode-eu__list_integrations.
Part 3: Self-Service Actions for CRDs
Create Port self-service actions that trigger GitHub workflows to manage CRD manifests.
Step 0: Configure GitHub Repository Secrets
Use
gh secret set to add required secrets:
- Port client IDPORT_CLIENT_ID
- Port client secretPORT_CLIENT_SECRET
- (Only for non-GitOps) Base64-encoded kubeconfigKUBE_CONFIG
Step 1: Create GitHub Workflows
Create workflow for each CRD with
workflow_dispatch trigger accepting:
(create/update/delete)action
,namenamespace- Resource-specific inputs
port_run_id
Workflow steps:
- Checkout repository
- Report "RUNNING" status to Port using
port-labs/port-github-action@v1 - Create/update/delete manifest in the configured manifest directory
- Commit and push to Git
- Non-GitOps only: Run
orkubectl applykubectl delete - Report "SUCCESS" or "FAILURE" to Port
Step 2: Create Port Self-Service Actions
Create 3 actions per CRD using Port MCP tools:
- CREATE - Creates new resources (no entity context)
- DAY-2 - Updates existing resources (has entity context)
- DELETE - Deletes resources (has entity context)
Key template expressions:
- User input value{{ .inputs.fieldName }}
- Port action run ID{{ .run.id }}
- Entity identifier (for DAY-2/DELETE){{ .entity.identifier }}
- Extract resource name from identifier{{ .entity.identifier | split("-") | last }}
For DAY-2 actions, pre-populate inputs with current entity values:
"default": { "jqQuery": ".entity.properties.someField // \"default_value\"" }