cortexapps-cli 1.31.0__tar.gz → 1.32.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (209) hide show
  1. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/PKG-INFO +1 -1
  2. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations.py +2 -0
  3. cortexapps_cli-1.32.0/cortexapps_cli/commands/integrations_commands/harness.py +160 -0
  4. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/solutions.py +3 -3
  5. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/_lib/setup_base.py +27 -13
  6. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/github-actions-deploy/setup.py +6 -9
  7. cortexapps_cli-1.32.0/cortexapps_cli/solutions/harness-deploy/README.md +112 -0
  8. cortexapps_cli-1.32.0/cortexapps_cli/solutions/harness-deploy/_templates/cortex-async-callback-template.yaml +59 -0
  9. cortexapps_cli-1.32.0/cortexapps_cli/solutions/harness-deploy/_templates/cortex-deploy-pipeline.yaml +110 -0
  10. cortexapps_cli-1.32.0/cortexapps_cli/solutions/harness-deploy/_templates/cortex-record-deploy-template.yaml +55 -0
  11. cortexapps_cli-1.32.0/cortexapps_cli/solutions/harness-deploy/_templates/trigger-harness-deploy.yaml +177 -0
  12. cortexapps_cli-1.32.0/cortexapps_cli/solutions/harness-deploy/catalog/harness-demo.yaml +14 -0
  13. cortexapps_cli-1.32.0/cortexapps_cli/solutions/harness-deploy/scorecards/deploy-health.yaml +51 -0
  14. cortexapps_cli-1.32.0/cortexapps_cli/solutions/harness-deploy/setup.py +520 -0
  15. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/pyproject.toml +1 -1
  16. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/LICENSE +0 -0
  17. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/README.rst +0 -0
  18. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/__init__.py +0 -0
  19. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/cli.py +0 -0
  20. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/command_options.py +0 -0
  21. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/ai_skills.py +0 -0
  22. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/api_keys.py +0 -0
  23. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/audit_logs.py +0 -0
  24. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/backup.py +0 -0
  25. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/backup_commands/cortex_export.py +0 -0
  26. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/catalog.py +0 -0
  27. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/custom_data.py +0 -0
  28. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/custom_events.py +0 -0
  29. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/custom_metrics.py +0 -0
  30. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/dependencies.py +0 -0
  31. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/deploys.py +0 -0
  32. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/discovery_audit.py +0 -0
  33. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/docs.py +0 -0
  34. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/entity_relationship_types.py +0 -0
  35. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/entity_relationships.py +0 -0
  36. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/entity_types.py +0 -0
  37. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/gitops_logs.py +0 -0
  38. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/groups.py +0 -0
  39. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/initiatives.py +0 -0
  40. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/apiiro.py +0 -0
  41. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/argocd.py +0 -0
  42. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/aws.py +0 -0
  43. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/azure_active_directory.py +0 -0
  44. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/azure_devops.py +0 -0
  45. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/azure_resources.py +0 -0
  46. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/bamboohr.py +0 -0
  47. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/bitbucket.py +0 -0
  48. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/bugsnag.py +0 -0
  49. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/buildkite.py +0 -0
  50. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/checkmarx_sast.py +0 -0
  51. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/circleci.py +0 -0
  52. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/clickup.py +0 -0
  53. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/codecov.py +0 -0
  54. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/coralogix.py +0 -0
  55. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/datadog.py +0 -0
  56. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/dynatrace.py +0 -0
  57. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/firehydrant.py +0 -0
  58. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/github.py +0 -0
  59. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/gitlab.py +0 -0
  60. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/incidentio.py +0 -0
  61. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/instana.py +0 -0
  62. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/jenkins.py +0 -0
  63. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/jira.py +0 -0
  64. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/launchdarkly.py +0 -0
  65. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/mend_sast.py +0 -0
  66. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/mend_sca.py +0 -0
  67. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/newrelic.py +0 -0
  68. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/okta.py +0 -0
  69. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/opsgenie.py +0 -0
  70. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/pagerduty.py +0 -0
  71. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/prometheus.py +0 -0
  72. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/rollbar.py +0 -0
  73. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/rootly.py +0 -0
  74. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/semgrep.py +0 -0
  75. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/sentry.py +0 -0
  76. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/servicenow.py +0 -0
  77. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/servicenow_cloud_observability.py +0 -0
  78. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/snyk.py +0 -0
  79. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/sonarqube.py +0 -0
  80. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/splunk_observability_cloud.py +0 -0
  81. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/splunk_on_call.py +0 -0
  82. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/sumologic.py +0 -0
  83. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/veracode.py +0 -0
  84. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/wiz.py +0 -0
  85. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/workday.py +0 -0
  86. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/xmatters.py +0 -0
  87. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/ip_allowlist.py +0 -0
  88. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/on_call.py +0 -0
  89. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/packages.py +0 -0
  90. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/packages_commands/go.py +0 -0
  91. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/packages_commands/java.py +0 -0
  92. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/packages_commands/node.py +0 -0
  93. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/packages_commands/nuget.py +0 -0
  94. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/packages_commands/python.py +0 -0
  95. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/plugins.py +0 -0
  96. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/queries.py +0 -0
  97. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/rest.py +0 -0
  98. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/scim.py +0 -0
  99. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/scorecards.py +0 -0
  100. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/scorecards_commands/exemptions.py +0 -0
  101. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/secrets.py +0 -0
  102. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/teams.py +0 -0
  103. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/users.py +0 -0
  104. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/users_commands/roles.py +0 -0
  105. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/workflows.py +0 -0
  106. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/cortex_client.py +0 -0
  107. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/models/team.py +0 -0
  108. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/__init__.py +0 -0
  109. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/_lib/__init__.py +0 -0
  110. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-agents/README.md +0 -0
  111. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-agents/catalog/address-reviews.yaml +0 -0
  112. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-agents/catalog/audit-flags.yaml +0 -0
  113. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-agents/catalog/code-review.yaml +0 -0
  114. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-agents/catalog/fix-issue.yaml +0 -0
  115. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-agents/catalog/incident-trends.yaml +0 -0
  116. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-agents/catalog/jira-to-kb.yaml +0 -0
  117. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-agents/catalog/release-to-sha.yaml +0 -0
  118. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-agents/catalog/search-troubleshooting-kb.yaml +0 -0
  119. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-agents/catalog/simplify-test.yaml +0 -0
  120. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-agents/entity-types/ai-agent.json +0 -0
  121. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-agents/scorecards/ai-agent-governance.yaml +0 -0
  122. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-skills/README.md +0 -0
  123. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-skills/catalog/api-doc-sync.yaml +0 -0
  124. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-skills/catalog/changelog-writer.yaml +0 -0
  125. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-skills/catalog/docs-generator.yaml +0 -0
  126. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-skills/catalog/docs-portal.yaml +0 -0
  127. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-skills/entity-relationship-types/ai-plugin-service.json +0 -0
  128. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-skills/entity-relationship-types/ai-plugin-skills.json +0 -0
  129. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-skills/entity-relationship-types/ai-skill-service.json +0 -0
  130. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-skills/entity-types/ai-plugin.json +0 -0
  131. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-skills/entity-types/ai-skill.json +0 -0
  132. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-skills/scorecards/ai-skills-quality.yaml +0 -0
  133. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-spend/.github/workflows/sync-claude-spend.yaml +0 -0
  134. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-spend/README.md +0 -0
  135. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-spend/catalog/employee-alice-chen.yaml +0 -0
  136. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-spend/catalog/employee-bob-martinez.yaml +0 -0
  137. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-spend/catalog/employee-carol-kim.yaml +0 -0
  138. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-spend/catalog/employee-david-osei.yaml +0 -0
  139. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-spend/catalog/employee-emma-johnson.yaml +0 -0
  140. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-spend/catalog/team-data.yaml +0 -0
  141. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-spend/catalog/team-engineering.yaml +0 -0
  142. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-spend/catalog/team-frontend.yaml +0 -0
  143. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-spend/catalog/team-platform.yaml +0 -0
  144. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-spend/custom-metrics/ai-spend.json +0 -0
  145. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-spend/entity-relationship-types/team-member.json +0 -0
  146. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-spend/entity-types/employee.json +0 -0
  147. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-spend/plugins/team-ai-spend.json +0 -0
  148. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-spend/scorecards/ai-spend-scorecard.yaml +0 -0
  149. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-spend/scripts/sync-claude-spend.py +0 -0
  150. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/.github/workflows/cortex-service-version.yaml +0 -0
  151. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/README.md +0 -0
  152. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/api-gateway-3.0.1.yaml +0 -0
  153. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/api-gateway-3.1.0.yaml +0 -0
  154. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/api-gateway-3.1.1.yaml +0 -0
  155. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/api-gateway.yaml +0 -0
  156. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/auth-2.1.0.yaml +0 -0
  157. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/auth-2.1.1.yaml +0 -0
  158. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/auth-2.2.0.yaml +0 -0
  159. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/auth.yaml +0 -0
  160. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/aws-dev-us-west-2.yaml +0 -0
  161. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/billing-1.1.0.yaml +0 -0
  162. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/billing-1.2.0.yaml +0 -0
  163. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/billing.yaml +0 -0
  164. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/cart-1.0.2.yaml +0 -0
  165. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/cart.yaml +0 -0
  166. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/checkout-2.2.0.yaml +0 -0
  167. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/checkout-2.3.0.yaml +0 -0
  168. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/checkout-2.4.0.yaml +0 -0
  169. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/checkout.yaml +0 -0
  170. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/gcp-prod-us-east-1.yaml +0 -0
  171. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/gcp-prod-us-west-1.yaml +0 -0
  172. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/gcp-staging-us-east-1.yaml +0 -0
  173. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/notifications-1.0.0.yaml +0 -0
  174. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/notifications-1.0.1.yaml +0 -0
  175. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/notifications-1.1.0.yaml +0 -0
  176. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/notifications.yaml +0 -0
  177. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/order-service-2.0.1.yaml +0 -0
  178. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/order-service-2.1.0.yaml +0 -0
  179. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/order-service.yaml +0 -0
  180. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/payments-1.6.1.yaml +0 -0
  181. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/payments-1.7.0.yaml +0 -0
  182. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/payments-1.7.1.yaml +0 -0
  183. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/payments.yaml +0 -0
  184. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/release-2026-06-20.yaml +0 -0
  185. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/release-2026-07-01.yaml +0 -0
  186. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/release-2026-07-09.yaml +0 -0
  187. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/release-2026-07-10.yaml +0 -0
  188. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/search-4.0.0.yaml +0 -0
  189. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/search-4.1.0.yaml +0 -0
  190. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/search.yaml +0 -0
  191. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/user-service-1.2.0.yaml +0 -0
  192. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/user-service-1.3.0.yaml +0 -0
  193. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/user-service.yaml +0 -0
  194. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/entity-relationship-types/environments.json +0 -0
  195. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/entity-relationship-types/versions.json +0 -0
  196. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/entity-types/environment.json +0 -0
  197. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/entity-types/release.json +0 -0
  198. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/entity-types/service-version.json +0 -0
  199. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/workflows/create-environment.yaml +0 -0
  200. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/workflows/create-release.yaml +0 -0
  201. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/workflows/trigger-github-release.yaml +0 -0
  202. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/github-actions-deploy/README.md +0 -0
  203. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/github-actions-deploy/_templates/cortex-async-callback.yml +0 -0
  204. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/github-actions-deploy/_templates/cortex-deploy.yml +0 -0
  205. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/github-actions-deploy/_templates/cortex-register-deploy.yml +0 -0
  206. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/github-actions-deploy/_templates/github-actions-deploy.yaml +0 -0
  207. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/github-actions-deploy/catalog/github-actions-demo.yaml +0 -0
  208. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/github-actions-deploy/scorecards/deploy-health.yaml +0 -0
  209. {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cortexapps-cli
3
- Version: 1.31.0
3
+ Version: 1.32.0
4
4
  Summary: Command Line Interface for cortexapps
5
5
  License: MIT
6
6
  License-File: LICENSE
@@ -23,6 +23,7 @@ import cortexapps_cli.commands.integrations_commands.dynatrace as dynatrace
23
23
  import cortexapps_cli.commands.integrations_commands.firehydrant as firehydrant
24
24
  import cortexapps_cli.commands.integrations_commands.github as github
25
25
  import cortexapps_cli.commands.integrations_commands.gitlab as gitlab
26
+ import cortexapps_cli.commands.integrations_commands.harness as harness
26
27
  import cortexapps_cli.commands.integrations_commands.incidentio as incidentio
27
28
  import cortexapps_cli.commands.integrations_commands.instana as instana
28
29
  import cortexapps_cli.commands.integrations_commands.jenkins as jenkins
@@ -72,6 +73,7 @@ app.add_typer(dynatrace.app, name="dynatrace")
72
73
  app.add_typer(firehydrant.app, name="firehydrant")
73
74
  app.add_typer(github.app, name="github")
74
75
  app.add_typer(gitlab.app, name="gitlab")
76
+ app.add_typer(harness.app, name="harness")
75
77
  app.add_typer(incidentio.app, name="incidentio")
76
78
  app.add_typer(instana.app, name="instana")
77
79
  app.add_typer(jenkins.app, name="jenkins")
@@ -0,0 +1,160 @@
1
+ import json
2
+ from rich import print_json
3
+ import typer
4
+ from typing_extensions import Annotated
5
+
6
+ app = typer.Typer(help="Harness commands", no_args_is_help=True)
7
+
8
+
9
+ @app.command()
10
+ def add(
11
+ ctx: typer.Context,
12
+ alias: str = typer.Option(..., "--alias", "-a", help="Alias for this configuration"),
13
+ api_key: str = typer.Option(..., "--api-key", "-k", help="Harness API key"),
14
+ account_id: str = typer.Option(..., "--account-id", "-id", help="Harness account ID"),
15
+ host: str = typer.Option(None, "--host", "-h", help="Harness host URL (optional; defaults to https://app.harness.io)"),
16
+ is_default: bool = typer.Option(False, "--is-default", "-i", help="Set as the default configuration"),
17
+ file_input: Annotated[typer.FileText, typer.Option("--file", "-f", help="JSON file containing configuration; use - for stdin")] = None,
18
+ ):
19
+ """
20
+ Add a Harness configuration
21
+ """
22
+ client = ctx.obj["client"]
23
+
24
+ if file_input:
25
+ if alias or api_key or account_id or host or is_default:
26
+ raise typer.BadParameter("When providing a configuration file, do not specify any other attributes")
27
+ data = json.loads("".join([line for line in file_input]))
28
+ else:
29
+ data = {
30
+ "alias": alias,
31
+ "apiKey": api_key,
32
+ "accountId": account_id,
33
+ "isDefault": is_default,
34
+ }
35
+ if host is not None:
36
+ data["host"] = host
37
+
38
+ r = client.post("api/v1/harness/configuration", data=data)
39
+ print_json(data=r)
40
+
41
+
42
+ @app.command()
43
+ def get(
44
+ ctx: typer.Context,
45
+ alias: str = typer.Option(..., "--alias", "-a", help="Alias of the configuration to retrieve"),
46
+ ):
47
+ """
48
+ Get a single Harness configuration by alias
49
+ """
50
+ client = ctx.obj["client"]
51
+ r = client.get(f"api/v1/harness/configuration/{alias}")
52
+ print_json(data=r)
53
+
54
+
55
+ @app.command()
56
+ def list(
57
+ ctx: typer.Context,
58
+ ):
59
+ """
60
+ List all Harness configurations
61
+ """
62
+ client = ctx.obj["client"]
63
+ r = client.get("api/v1/harness/configurations")
64
+ print_json(data=r)
65
+
66
+
67
+ @app.command()
68
+ def get_default(
69
+ ctx: typer.Context,
70
+ ):
71
+ """
72
+ Get the default Harness configuration
73
+ """
74
+ client = ctx.obj["client"]
75
+ r = client.get("api/v1/harness/default-configuration")
76
+ print_json(data=r)
77
+
78
+
79
+ @app.command()
80
+ def update(
81
+ ctx: typer.Context,
82
+ alias: str = typer.Option(..., "--alias", "-a", help="Alias of the configuration to update"),
83
+ api_key: str = typer.Option(None, "--api-key", "-k", help="New Harness API key"),
84
+ account_id: str = typer.Option(None, "--account-id", "-id", help="New Harness account ID"),
85
+ host: str = typer.Option(None, "--host", "-h", help="New Harness host URL"),
86
+ is_default: bool = typer.Option(None, "--is-default", "-i", help="Set as the default configuration"),
87
+ file_input: Annotated[typer.FileText, typer.Option("--file", "-f", help="JSON file containing update fields; use - for stdin")] = None,
88
+ ):
89
+ """
90
+ Update a Harness configuration
91
+ """
92
+ client = ctx.obj["client"]
93
+
94
+ if file_input:
95
+ if alias or api_key or account_id or host or is_default is not None:
96
+ raise typer.BadParameter("When providing a configuration file, do not specify any other attributes")
97
+ data = json.loads("".join([line for line in file_input]))
98
+ else:
99
+ data = {}
100
+ if api_key is not None:
101
+ data["apiKey"] = api_key
102
+ if account_id is not None:
103
+ data["accountId"] = account_id
104
+ if host is not None:
105
+ data["host"] = host
106
+ if is_default is not None:
107
+ data["isDefault"] = is_default
108
+
109
+ r = client.put(f"api/v1/harness/configuration/{alias}", data=data)
110
+ print_json(data=r)
111
+
112
+
113
+ @app.command()
114
+ def delete(
115
+ ctx: typer.Context,
116
+ alias: str = typer.Option(..., "--alias", "-a", help="Alias of the configuration to delete"),
117
+ ):
118
+ """
119
+ Delete a single Harness configuration
120
+ """
121
+ client = ctx.obj["client"]
122
+ r = client.delete(f"api/v1/harness/configuration/{alias}")
123
+ print_json(data=r)
124
+
125
+
126
+ @app.command()
127
+ def delete_all(
128
+ ctx: typer.Context,
129
+ ):
130
+ """
131
+ Delete all Harness configurations
132
+ """
133
+ client = ctx.obj["client"]
134
+ r = client.delete("api/v1/harness/configurations")
135
+ print_json(data=r)
136
+
137
+
138
+ @app.command()
139
+ def validate(
140
+ ctx: typer.Context,
141
+ alias: str = typer.Option(..., "--alias", "-a", help="Alias of the configuration to validate"),
142
+ ):
143
+ """
144
+ Validate a single Harness configuration
145
+ """
146
+ client = ctx.obj["client"]
147
+ r = client.post(f"api/v1/harness/configuration/validate/{alias}")
148
+ print_json(data=r)
149
+
150
+
151
+ @app.command()
152
+ def validate_all(
153
+ ctx: typer.Context,
154
+ ):
155
+ """
156
+ Validate all Harness configurations
157
+ """
158
+ client = ctx.obj["client"]
159
+ r = client.post("api/v1/harness/configuration/validate")
160
+ print_json(data=r)
@@ -400,10 +400,10 @@ def _run_uninstall(client, path: Path, yes: bool) -> None:
400
400
  total = sum(len(v) for v in resources.values())
401
401
 
402
402
  if total == 0:
403
- typer.echo("No resources found to remove.")
403
+ typer.echo("No entities found to remove.")
404
404
  return
405
405
 
406
- typer.echo("\nThis will remove the following resources:")
406
+ typer.echo("\nThis will remove the following entities:")
407
407
  for kind in ("workflows", "scorecards", "plugins", "catalog", "entity-relationship-types", "entity-types"):
408
408
  count = len(resources[kind])
409
409
  if count:
@@ -701,7 +701,7 @@ def install(
701
701
  typer.echo(failed_m.group(0))
702
702
  typer.echo(f"\n {total_imported} imported, {total_failed} failed")
703
703
  else:
704
- typer.echo(f" {total_imported} resources imported")
704
+ typer.echo(f" {total_imported} entities imported")
705
705
  else:
706
706
  typer.echo(output)
707
707
 
@@ -17,6 +17,7 @@ class SolutionSetup(ABC):
17
17
 
18
18
  def __init__(self, state_dir: Optional[Path] = None, no_prompt: bool = False):
19
19
  self._no_prompt = no_prompt
20
+ self._save_answers = True
20
21
  self._secret_keys: set = set()
21
22
  self._answers: dict = {}
22
23
 
@@ -39,10 +40,12 @@ class SolutionSetup(ABC):
39
40
  return {}
40
41
 
41
42
  def _save_file(self) -> None:
42
- data = {
43
- "answers": {k: v for k, v in self._answers.items() if k not in self._secret_keys},
44
- "state": self._state,
45
- }
43
+ saved_answers = (
44
+ {k: v for k, v in self._answers.items() if k not in self._secret_keys}
45
+ if self._save_answers
46
+ else {}
47
+ )
48
+ data = {"answers": saved_answers, "state": self._state}
46
49
  self._state_file.write_text(json.dumps(data, indent=2))
47
50
 
48
51
  def _save_state(self) -> None:
@@ -69,23 +72,29 @@ class SolutionSetup(ABC):
69
72
  env_var: Optional[str] = None,
70
73
  default: Optional[str] = None,
71
74
  secret: bool = False,
75
+ hidden: bool = False,
72
76
  ) -> str:
73
- """Prompt for a value. Uses saved answer or env var when available."""
77
+ """Prompt for a value. Uses saved answer or env var when available.
78
+
79
+ secret=True — mask input AND exclude from saved JSON
80
+ hidden=True — mask input only; value is still saved to JSON
81
+ """
82
+ use_getpass = secret or hidden
74
83
  if secret:
75
84
  self._secret_keys.add(key)
76
85
 
77
- # Non-secret: use saved answer when --no-prompt
86
+ # Use saved answer when --no-prompt (works for both plain and hidden keys)
78
87
  if self._no_prompt and not secret and key in self._answers:
79
88
  return self._answers[key]
80
89
 
81
- # Non-secret: saved answer takes precedence over any derived default
90
+ # Saved answer takes precedence over any derived default
82
91
  if not secret and key in self._answers:
83
92
  default = self._answers[key]
84
93
 
85
94
  if env_var:
86
95
  env_val = os.environ.get(env_var)
87
96
  if env_val:
88
- masked = "********" if secret else env_val
97
+ masked = "********" if use_getpass else env_val
89
98
  if self._no_prompt or self.confirm(f"{message} [{masked} from {env_var}]", default=True):
90
99
  self._answers[key] = env_val
91
100
  return env_val
@@ -94,12 +103,15 @@ class SolutionSetup(ABC):
94
103
  if self._no_prompt and secret and key not in self._answers:
95
104
  print(f" (secret required — no env var set for {key})", file=sys.stderr)
96
105
 
97
- prompt_str = message
98
- if default:
99
- prompt_str += f" [{default}]"
100
- prompt_str += ": "
106
+ if use_getpass and default:
107
+ hint = f"********{default[-4:]}"
108
+ elif default:
109
+ hint = default
110
+ else:
111
+ hint = None
112
+ prompt_str = f"{message} [{hint}]: " if hint else f"{message}: "
101
113
 
102
- if secret:
114
+ if use_getpass:
103
115
  value = getpass.getpass(prompt_str).strip()
104
116
  else:
105
117
  value = input(prompt_str).strip()
@@ -147,6 +159,8 @@ class SolutionSetup(ABC):
147
159
  for k, v in saved.items():
148
160
  print(f" {k}: {v}")
149
161
  print()
162
+ elif not self._no_prompt:
163
+ self._save_answers = self.confirm(f"Save answers for future runs to {self._state_file}", default=True)
150
164
 
151
165
  self.collect_prompts()
152
166
  self._save_file()
@@ -163,20 +163,17 @@ class GitHubActionsSetup(SolutionSetup):
163
163
  self.prompt("github_owner", "GitHub org or username", default=default_owner)
164
164
  self.prompt("repo_name", "Repository name", default="cortex-deploy-demo")
165
165
 
166
- # 3. Cortex credentials from CLI session
166
+ # 3. Cortex credentials use CLI session silently; only prompt when running standalone
167
+ self._secret_keys.add("cortex_api_key")
167
168
  if self._session_api_key:
168
- if self.confirm("Use Cortex API key used by this CLI session?", default=True):
169
- self._answers["cortex_api_key"] = self._session_api_key
170
- else:
171
- self.prompt("cortex_api_key", "Cortex API key", secret=True)
169
+ self._answers["cortex_api_key"] = self._session_api_key
172
170
  else:
173
171
  self.prompt("cortex_api_key", "Cortex API key", env_var="CORTEX_API_KEY", secret=True)
174
172
 
175
173
  if self._session_base_url:
176
- if self.confirm(f"Use Cortex base URL used by this CLI session [{self._session_base_url}]?", default=True):
177
- self._answers["cortex_base_url"] = self._session_base_url
178
- else:
179
- self.prompt("cortex_base_url", "Cortex base URL", default=self._session_base_url)
174
+ self._answers["cortex_base_url"] = self._session_base_url
175
+ else:
176
+ self.prompt("cortex_base_url", "Cortex base URL", default=self._session_base_url)
180
177
  else:
181
178
  self.prompt(
182
179
  "cortex_base_url",
@@ -0,0 +1,112 @@
1
+ ---
2
+ name: Harness Deploy Tracking
3
+ description: Track deployments from Harness pipelines in Cortex, with a deploy health scorecard measuring delivery cadence.
4
+ ---
5
+
6
+ # Harness Deploy Tracking
7
+
8
+ Trigger deploys from Cortex, track them as they run in Harness, and surface deploy health back in your service catalog.
9
+
10
+ ```
11
+ ┌─────────────────────────────────┐
12
+ │ Cortex Catalog │
13
+ │ │
14
+ │ harness-demo (service) │
15
+ │ └── Scorecard: Deploy Health │
16
+ │ Bronze / Silver / Gold │
17
+ └──────────────┬──────────────────┘
18
+
19
+ │ Run workflow from entity page
20
+ │ (or: cortex workflows run -t
21
+ │ harness-trigger-deploy
22
+ │ --scope ENTITY --entity <tag>)
23
+
24
+ ┌─────────────────────────────────┐
25
+ │ Cortex Workflow │
26
+ │ Trigger Harness Deploy │
27
+ │ │
28
+ │ 1. Read Harness config from │
29
+ │ entity custom metadata │
30
+ │ 2. POST /execute to Harness │
31
+ │ pipeline via integration │
32
+ │ 3. Pass callback URL as │
33
+ │ pipeline variable │
34
+ │ 4. Wait for callback │
35
+ └──────────────┬──────────────────┘
36
+ │ POST /execute (Harness integration)
37
+
38
+ ┌─────────────────────────────────┐
39
+ │ Harness Pipeline │
40
+ │ cortex-deploy │
41
+ │ │
42
+ │ stage: Build │
43
+ │ └── run your deploy steps │
44
+ │ │
45
+ │ stage: Record Deploy in Cortex │
46
+ │ └── POST /deploys ◄────┼── registers deploy event
47
+ │ (entity: harness-demo) │ on the Cortex entity
48
+ │ │
49
+ │ stage: Callback to Cortex │
50
+ │ └── POST callbackUrl ───────►│ Cortex marks workflow
51
+ │ status: SUCCESS/FAILURE │ run complete
52
+ └─────────────────────────────────┘
53
+ ```
54
+
55
+ ## What's Included
56
+
57
+ - **Entity:** `harness-demo` service — a sample entity to receive deploy events
58
+ - **Scorecard:** Deploy Health — Bronze/Silver/Gold based on deploy frequency
59
+ - **Harness stage templates:** `cortex_record_deploy` and `cortex_async_callback` — reusable Stage Templates that register the deploy event and call back to Cortex; reference them from any pipeline
60
+ - **Harness pipeline:** `cortex-deploy` — a three-stage demo pipeline (Build → Record Deploy in Cortex → Callback to Cortex) created in your Harness project
61
+ - **Cortex workflow:** `harness-trigger-deploy` — reads Harness coordinates from entity custom metadata, triggers the pipeline via the Harness integration, and waits for the result
62
+ - **Setup script:** Interactive wizard that wires everything together end-to-end
63
+
64
+ ## Quick Start
65
+
66
+ 1. Install the solution:
67
+
68
+ ```
69
+ cortex solutions install -s harness-deploy
70
+ ```
71
+
72
+ 2. Follow the post-install setup prompts, or run later:
73
+
74
+ ```
75
+ cortex solutions post-install -s harness-deploy
76
+ ```
77
+
78
+ ## How It Works
79
+
80
+ The Cortex workflow triggers `cortex-deploy` via the Harness integration, passing a `callback_url` as a pipeline variable. Cortex waits asynchronously for the pipeline to report back.
81
+
82
+ Harness runs the build, then notifies Cortex twice on completion:
83
+ - **Deploy registration** (`POST /api/v1/catalog/{tag}/deploys`) — records the deploy event on the entity, feeding the Deploy Health scorecard
84
+ - **Workflow callback** — signals the Cortex workflow run as SUCCESS or FAILURE
85
+
86
+ ## After Installing
87
+
88
+ If you ran the post-install setup, you're already done — it configured the Harness integration, created the pipeline and `cortex_api_key` secret in Harness, imported the Cortex workflow, and triggered a test deploy.
89
+
90
+ To roll the pattern out to your own services:
91
+
92
+ 1. Add both **Cortex Record Deploy** and **Cortex Async Callback** stage templates to any existing Harness pipeline (each needs only the `cortex_api_key` secret and its one pipeline variable)
93
+
94
+ 2. Add a `x-cortex-custom-metadata` block to your entity's catalog YAML with your Harness coordinates:
95
+
96
+ ```yaml
97
+ x-cortex-custom-metadata:
98
+ harness:
99
+ org: your-org
100
+ project: your-project
101
+ pipeline: your-pipeline-id
102
+ ```
103
+
104
+ 3. Run the **Solution: Trigger Harness Deploy** workflow from the entity page — it reads the Harness coordinates from the entity's custom metadata automatically, with no manual inputs required
105
+
106
+ > **Note:** The custom metadata approach is a stand-in for a native Harness integration that is in development. Once released, Harness coordinates will likely be read directly from the integration config rather than custom metadata.
107
+
108
+ ## Customizing for Production
109
+
110
+ - Point the workflow at your real entity by replacing `harness-demo` with your service tag
111
+ - Add the `cortex_api_key` secret to your real Harness projects
112
+ - The Deploy Health scorecard is scoped to `demo-harness-deploys` to avoid affecting your existing services. To roll it out broadly, remove the group filter from the scorecard. To opt in individual services, add the `demo-harness-deploys` group to them.
@@ -0,0 +1,59 @@
1
+ template:
2
+ name: Cortex Async Callback
3
+ identifier: cortex_async_callback
4
+ versionLabel: "1.0"
5
+ type: Stage
6
+ orgIdentifier: default
7
+ projectIdentifier: default_project
8
+ spec:
9
+ type: Custom
10
+ spec:
11
+ execution:
12
+ steps:
13
+ - step:
14
+ name: Callback to Cortex
15
+ identifier: cortex_callback
16
+ type: ShellScript
17
+ spec:
18
+ shell: Bash
19
+ executionTarget: {}
20
+ source:
21
+ type: Inline
22
+ spec:
23
+ script: |
24
+ if [ -z "$CALLBACK_URL" ]; then
25
+ echo "No callback URL set, skipping"
26
+ exit 0
27
+ fi
28
+
29
+ EXECUTION_URL="https://app.harness.io/ng/account/$HARNESS_ACCOUNT_ID/cd/orgs/<+pipeline.orgIdentifier>/projects/<+pipeline.projectIdentifier>/pipelines/<+pipeline.identifier>/executions/<+pipeline.executionId>/pipeline"
30
+
31
+ PAYLOAD="{\"status\":\"SUCCESS\",\"message\":\"Pipeline completed successfully\",\"response\":{\"execution_id\":\"<+pipeline.executionId>\",\"execution_number\":\"<+pipeline.sequenceId>\",\"pipeline_name\":\"<+pipeline.name>\",\"pipeline_url\":\"$EXECUTION_URL\"}}"
32
+
33
+ HTTP_STATUS=$(curl -s -o /tmp/cb_response.txt -w "%{http_code}" -X POST "$CALLBACK_URL" \
34
+ -H "Content-Type: application/json" \
35
+ -H "Authorization: Bearer $CORTEX_API_KEY" \
36
+ -d "$PAYLOAD")
37
+
38
+ echo "Callback HTTP status: $HTTP_STATUS"
39
+ cat /tmp/cb_response.txt
40
+ if [ "$HTTP_STATUS" != "200" ]; then
41
+ echo "ERROR: Callback failed with HTTP $HTTP_STATUS"
42
+ exit 1
43
+ fi
44
+ environmentVariables:
45
+ - name: CALLBACK_URL
46
+ type: String
47
+ value: "<+stage.variables.callback_url>"
48
+ - name: CORTEX_API_KEY
49
+ type: Secret
50
+ value: cortex_api_key
51
+ - name: HARNESS_ACCOUNT_ID
52
+ type: String
53
+ value: "<+account.identifier>"
54
+ outputVariables: []
55
+ timeout: 10m
56
+ variables:
57
+ - name: callback_url
58
+ type: String
59
+ value: <+input>
@@ -0,0 +1,110 @@
1
+ pipeline:
2
+ name: Cortex Deploy
3
+ identifier: cortex_deploy
4
+ orgIdentifier: default
5
+ projectIdentifier: default_project
6
+ description: "Sample Harness pipeline that registers a deploy event in Cortex and reports back to Cortex async workflows."
7
+ variables:
8
+ - name: callback_url
9
+ type: String
10
+ description: Cortex async callback URL (set automatically when triggered via Cortex workflow)
11
+ required: false
12
+ default: ""
13
+ value: "<+input>"
14
+ - name: cortex_entity_tag
15
+ type: String
16
+ description: Cortex entity tag to register the deploy against
17
+ required: false
18
+ default: "harness-demo"
19
+ value: "<+input>"
20
+ stages:
21
+ - stage:
22
+ name: Build
23
+ identifier: build
24
+ type: Custom
25
+ spec:
26
+ execution:
27
+ steps:
28
+ - step:
29
+ name: Build
30
+ identifier: build_step
31
+ type: ShellScript
32
+ spec:
33
+ shell: Bash
34
+ executionTarget: {}
35
+ source:
36
+ type: Inline
37
+ spec:
38
+ script: echo "Building..."
39
+ environmentVariables: []
40
+ outputVariables: []
41
+ timeout: 10m
42
+ - step:
43
+ name: Deploy Progress
44
+ identifier: deploy_progress
45
+ type: ShellScript
46
+ spec:
47
+ shell: Bash
48
+ executionTarget: {}
49
+ source:
50
+ type: Inline
51
+ spec:
52
+ script: |
53
+ # Sends intermediate UPDATE callbacks to the Cortex workflow,
54
+ # demonstrating that the callback URL can be called multiple times
55
+ # before the terminal SUCCESS/FAILURE.
56
+ if [ -z "$CALLBACK_URL" ]; then
57
+ echo "No callback URL set, skipping progress updates"
58
+ exit 0
59
+ fi
60
+
61
+ TOTAL_SECONDS=15
62
+ INTERVAL=5
63
+ ITERATIONS=$((TOTAL_SECONDS / INTERVAL))
64
+
65
+ for i in $(seq 1 $ITERATIONS); do
66
+ sleep $INTERVAL
67
+ PROGRESS=$((i * 100 / ITERATIONS))
68
+
69
+ curl -s -X POST "$CALLBACK_URL" \
70
+ -H "Authorization: Bearer $CORTEX_API_KEY" \
71
+ -H "Content-Type: application/json" \
72
+ -d "{\"status\":\"UPDATE\",\"message\":\"Job still running – progress update.\",\"response\":{\"progress\":\"${PROGRESS}%\",\"details\":\"Deploy in progress (${i}/${ITERATIONS} intervals completed)\"}}" || true
73
+
74
+ echo "Progress update ${i}/${ITERATIONS} (${PROGRESS}%) sent"
75
+ done
76
+ environmentVariables:
77
+ - name: CALLBACK_URL
78
+ type: String
79
+ value: "<+pipeline.variables.callback_url>"
80
+ - name: CORTEX_API_KEY
81
+ type: Secret
82
+ value: cortex_api_key
83
+ outputVariables: []
84
+ timeout: 5m
85
+
86
+ - stage:
87
+ name: Record Deploy in Cortex
88
+ identifier: record_deploy_stage
89
+ template:
90
+ templateRef: cortex_record_deploy
91
+ versionLabel: "1.0"
92
+ templateInputs:
93
+ type: Custom
94
+ variables:
95
+ - name: cortex_entity_tag
96
+ type: String
97
+ value: "<+pipeline.variables.cortex_entity_tag>"
98
+
99
+ - stage:
100
+ name: Callback to Cortex
101
+ identifier: callback_stage
102
+ template:
103
+ templateRef: cortex_async_callback
104
+ versionLabel: "1.0"
105
+ templateInputs:
106
+ type: Custom
107
+ variables:
108
+ - name: callback_url
109
+ type: String
110
+ value: "<+pipeline.variables.callback_url>"
@@ -0,0 +1,55 @@
1
+ template:
2
+ name: Cortex Record Deploy
3
+ identifier: cortex_record_deploy
4
+ versionLabel: "1.0"
5
+ type: Stage
6
+ orgIdentifier: default
7
+ projectIdentifier: default_project
8
+ spec:
9
+ type: Custom
10
+ spec:
11
+ execution:
12
+ steps:
13
+ - step:
14
+ name: Record Deploy
15
+ identifier: record_deploy
16
+ type: ShellScript
17
+ spec:
18
+ shell: Bash
19
+ executionTarget: {}
20
+ source:
21
+ type: Inline
22
+ spec:
23
+ script: |
24
+ RUN_URL="https://app.harness.io/ng/account/$HARNESS_ACCOUNT_ID/cd/orgs/<+pipeline.orgIdentifier>/projects/<+pipeline.projectIdentifier>/pipelines/<+pipeline.identifier>/executions/<+pipeline.executionId>/pipeline"
25
+ TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%SZ)
26
+ ACTOR="<+pipeline.triggeredBy.name>"
27
+ EXEC_ID="<+pipeline.executionId>"
28
+ SEQ_ID="<+pipeline.sequenceId>"
29
+
30
+ PAYLOAD="{\"sha\":\"$EXEC_ID\",\"timestamp\":\"$TIMESTAMP\",\"environment\":\"production\",\"type\":\"DEPLOY\",\"title\":\"Triggered by $ACTOR\",\"deployer\":{\"name\":\"$ACTOR\"},\"customData\":{\"executionId\":\"$EXEC_ID\",\"sequenceId\":\"$SEQ_ID\",\"executionUrl\":\"$RUN_URL\"}}"
31
+
32
+ curl -s -f -X POST \
33
+ "$CORTEX_BASE_URL/api/v1/catalog/$CORTEX_ENTITY_TAG/deploys" \
34
+ -H "Authorization: Bearer $CORTEX_API_KEY" \
35
+ -H "Content-Type: application/json" \
36
+ -d "$PAYLOAD" || true
37
+ environmentVariables:
38
+ - name: CORTEX_API_KEY
39
+ type: Secret
40
+ value: cortex_api_key
41
+ - name: CORTEX_BASE_URL
42
+ type: String
43
+ value: "https://api.getcortexapp.com"
44
+ - name: CORTEX_ENTITY_TAG
45
+ type: String
46
+ value: "<+stage.variables.cortex_entity_tag>"
47
+ - name: HARNESS_ACCOUNT_ID
48
+ type: String
49
+ value: "<+account.identifier>"
50
+ outputVariables: []
51
+ timeout: 5m
52
+ variables:
53
+ - name: cortex_entity_tag
54
+ type: String
55
+ value: <+input>