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.
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/PKG-INFO +1 -1
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations.py +2 -0
- cortexapps_cli-1.32.0/cortexapps_cli/commands/integrations_commands/harness.py +160 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/solutions.py +3 -3
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/_lib/setup_base.py +27 -13
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/github-actions-deploy/setup.py +6 -9
- cortexapps_cli-1.32.0/cortexapps_cli/solutions/harness-deploy/README.md +112 -0
- cortexapps_cli-1.32.0/cortexapps_cli/solutions/harness-deploy/_templates/cortex-async-callback-template.yaml +59 -0
- cortexapps_cli-1.32.0/cortexapps_cli/solutions/harness-deploy/_templates/cortex-deploy-pipeline.yaml +110 -0
- cortexapps_cli-1.32.0/cortexapps_cli/solutions/harness-deploy/_templates/cortex-record-deploy-template.yaml +55 -0
- cortexapps_cli-1.32.0/cortexapps_cli/solutions/harness-deploy/_templates/trigger-harness-deploy.yaml +177 -0
- cortexapps_cli-1.32.0/cortexapps_cli/solutions/harness-deploy/catalog/harness-demo.yaml +14 -0
- cortexapps_cli-1.32.0/cortexapps_cli/solutions/harness-deploy/scorecards/deploy-health.yaml +51 -0
- cortexapps_cli-1.32.0/cortexapps_cli/solutions/harness-deploy/setup.py +520 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/pyproject.toml +1 -1
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/LICENSE +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/README.rst +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/__init__.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/cli.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/command_options.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/ai_skills.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/api_keys.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/audit_logs.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/backup.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/backup_commands/cortex_export.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/catalog.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/custom_data.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/custom_events.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/custom_metrics.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/dependencies.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/deploys.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/discovery_audit.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/docs.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/entity_relationship_types.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/entity_relationships.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/entity_types.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/gitops_logs.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/groups.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/initiatives.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/apiiro.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/argocd.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/aws.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/azure_active_directory.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/azure_devops.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/azure_resources.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/bamboohr.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/bitbucket.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/bugsnag.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/buildkite.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/checkmarx_sast.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/circleci.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/clickup.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/codecov.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/coralogix.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/datadog.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/dynatrace.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/firehydrant.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/github.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/gitlab.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/incidentio.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/instana.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/jenkins.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/jira.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/launchdarkly.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/mend_sast.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/mend_sca.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/newrelic.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/okta.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/opsgenie.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/pagerduty.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/prometheus.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/rollbar.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/rootly.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/semgrep.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/sentry.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/servicenow.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/servicenow_cloud_observability.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/snyk.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/sonarqube.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/splunk_observability_cloud.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/splunk_on_call.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/sumologic.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/veracode.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/wiz.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/workday.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/integrations_commands/xmatters.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/ip_allowlist.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/on_call.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/packages.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/packages_commands/go.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/packages_commands/java.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/packages_commands/node.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/packages_commands/nuget.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/packages_commands/python.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/plugins.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/queries.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/rest.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/scim.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/scorecards.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/scorecards_commands/exemptions.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/secrets.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/teams.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/users.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/users_commands/roles.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/commands/workflows.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/cortex_client.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/models/team.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/__init__.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/_lib/__init__.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-agents/README.md +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-agents/catalog/address-reviews.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-agents/catalog/audit-flags.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-agents/catalog/code-review.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-agents/catalog/fix-issue.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-agents/catalog/incident-trends.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-agents/catalog/jira-to-kb.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-agents/catalog/release-to-sha.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-agents/catalog/search-troubleshooting-kb.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-agents/catalog/simplify-test.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-agents/entity-types/ai-agent.json +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-agents/scorecards/ai-agent-governance.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-skills/README.md +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-skills/catalog/api-doc-sync.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-skills/catalog/changelog-writer.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-skills/catalog/docs-generator.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-skills/catalog/docs-portal.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-skills/entity-relationship-types/ai-plugin-service.json +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-skills/entity-relationship-types/ai-plugin-skills.json +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-skills/entity-relationship-types/ai-skill-service.json +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-skills/entity-types/ai-plugin.json +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-skills/entity-types/ai-skill.json +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-skills/scorecards/ai-skills-quality.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-spend/.github/workflows/sync-claude-spend.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-spend/README.md +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-spend/catalog/employee-alice-chen.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-spend/catalog/employee-bob-martinez.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-spend/catalog/employee-carol-kim.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-spend/catalog/employee-david-osei.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-spend/catalog/employee-emma-johnson.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-spend/catalog/team-data.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-spend/catalog/team-engineering.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-spend/catalog/team-frontend.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-spend/catalog/team-platform.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-spend/custom-metrics/ai-spend.json +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-spend/entity-relationship-types/team-member.json +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-spend/entity-types/employee.json +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-spend/plugins/team-ai-spend.json +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-spend/scorecards/ai-spend-scorecard.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/ai-spend/scripts/sync-claude-spend.py +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/.github/workflows/cortex-service-version.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/README.md +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/api-gateway-3.0.1.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/api-gateway-3.1.0.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/api-gateway-3.1.1.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/api-gateway.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/auth-2.1.0.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/auth-2.1.1.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/auth-2.2.0.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/auth.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/aws-dev-us-west-2.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/billing-1.1.0.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/billing-1.2.0.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/billing.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/cart-1.0.2.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/cart.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/checkout-2.2.0.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/checkout-2.3.0.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/checkout-2.4.0.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/checkout.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/gcp-prod-us-east-1.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/gcp-prod-us-west-1.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/gcp-staging-us-east-1.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/notifications-1.0.0.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/notifications-1.0.1.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/notifications-1.1.0.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/notifications.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/order-service-2.0.1.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/order-service-2.1.0.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/order-service.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/payments-1.6.1.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/payments-1.7.0.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/payments-1.7.1.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/payments.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/release-2026-06-20.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/release-2026-07-01.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/release-2026-07-09.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/release-2026-07-10.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/search-4.0.0.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/search-4.1.0.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/search.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/user-service-1.2.0.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/user-service-1.3.0.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/catalog/user-service.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/entity-relationship-types/environments.json +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/entity-relationship-types/versions.json +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/entity-types/environment.json +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/entity-types/release.json +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/entity-types/service-version.json +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/workflows/create-environment.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/workflows/create-release.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/environments/workflows/trigger-github-release.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/github-actions-deploy/README.md +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/github-actions-deploy/_templates/cortex-async-callback.yml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/github-actions-deploy/_templates/cortex-deploy.yml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/github-actions-deploy/_templates/cortex-register-deploy.yml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/github-actions-deploy/_templates/github-actions-deploy.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/github-actions-deploy/catalog/github-actions-demo.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/solutions/github-actions-deploy/scorecards/deploy-health.yaml +0 -0
- {cortexapps_cli-1.31.0 → cortexapps_cli-1.32.0}/cortexapps_cli/utils.py +0 -0
|
@@ -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
|
|
403
|
+
typer.echo("No entities found to remove.")
|
|
404
404
|
return
|
|
405
405
|
|
|
406
|
-
typer.echo("\nThis will remove the following
|
|
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}
|
|
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
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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
|
-
#
|
|
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
|
-
#
|
|
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
|
|
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
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
177
|
-
|
|
178
|
-
|
|
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>
|
cortexapps_cli-1.32.0/cortexapps_cli/solutions/harness-deploy/_templates/cortex-deploy-pipeline.yaml
ADDED
|
@@ -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>
|