Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@ Commits use **conventional commit** prefixes which affect both versioning and ch

Best practice: Use `feat:` for new features (will bump minor) and `fix:` for bug fixes (will bump patch). These prefixes satisfy both the version bumping and changelog generation.

**Important**: `feat:` and `fix:` must only be used for commits that affect the CLI deliverable (i.e., changes under `cortexapps_cli/`, `pyproject.toml`, `poetry.lock`, `tests/`, `docker/`). Commits that only touch non-deliverable paths (`internal/`, `docs/superpowers/`, Justfile recipes for internal tooling, etc.) must use `chore:` or `docs:` prefixes to avoid unintended version bumps.

### HISTORY.md Merge Conflicts
The `HISTORY.md` file is auto-generated when `staging` is merged to `main`. This means:
- `main` always has the latest HISTORY.md
Expand Down
27 changes: 27 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,33 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

<!-- insertion marker -->
## [1.16.0](https://github.com/cortexapps/cli/releases/tag/1.16.0) - 2026-05-14

<small>[Compare with 1.15.0](https://github.com/cortexapps/cli/compare/1.15.0...1.16.0)</small>

### Features

- shared minikube cluster, env prompting, cortex deploy recipes ([ff7c67d](https://github.com/cortexapps/cli/commit/ff7c67db11b47c32be7018b1f8660d9e7e148ed7) by Jeff Schnitter).
- add Cortex Helm values and env vars for minikube deploy ([23a8994](https://github.com/cortexapps/cli/commit/23a89943e20164c73630fdaee0071cd88cc553f9) by Jeff Schnitter).
- consolidate internal tooling — axon, k8s, prometheus, ui, functional tests ([1fd70fe](https://github.com/cortexapps/cli/commit/1fd70fe5b212516704e91e0022c10e6c6c3aed3c) by Jeff Schnitter).
- add ske-setup, ske-test, and ske-stop Justfile recipes ([6f56dca](https://github.com/cortexapps/cli/commit/6f56dca1afcd48ebc23fe3cf5a70bc2760b60257) by Jeff Schnitter).
- add SKE Helm values and ArgoCD Application manifest ([3d83ca5](https://github.com/cortexapps/cli/commit/3d83ca567861c64cea08d2dedee545fee0aff278) by Jeff Schnitter).
- add ConfigMap Promise for SKE Cortex integration test ([7942967](https://github.com/cortexapps/cli/commit/7942967b83eb121fbd2ec606a14dfd86c5a73036) by Jeff Schnitter).
- add SKE directory structure and env config ([dc0cd54](https://github.com/cortexapps/cli/commit/dc0cd54e6126bc4e5f3498db85f7cf862ea261c2) by Jeff Schnitter).

### Bug Fixes

- add __init__.py to trigger publish workflow for urllib3 update ([854dcb0](https://github.com/cortexapps/cli/commit/854dcb00b534df21b6a1976c7a4e79fca613f246) by Jeff Schnitter).
- update urllib3 to 2.7.0 to resolve high-severity CVEs ([904a144](https://github.com/cortexapps/cli/commit/904a144e02e65067f2029d85baa5efdf83c535f6) by Jeff Schnitter).
- prompt for env vars before starting minikube ([3da7a87](https://github.com/cortexapps/cli/commit/3da7a870853591f48f0eb3e80013e0d6573f9f62) by Jeff Schnitter).
- review fixes — quote .env values, fix pod selector, remove dead PID files ([4931dae](https://github.com/cortexapps/cli/commit/4931daed4e8a10ab6b9842d6aa70e6b4ce81c94b) by Jeff Schnitter).
- use external script for env prompting to fix just quoting bug ([5816d65](https://github.com/cortexapps/cli/commit/5816d65c7ca55834b7eb0a1e819b5192d2463853) by Jeff Schnitter).
- use correct Cortex API endpoint for Entity Type check in ske-test ([94f774e](https://github.com/cortexapps/cli/commit/94f774e43d7849175224794cfd8c8d7744b6c925) by Jeff Schnitter).
- wait for cert-manager webhook CA, let SKE auto-create Destination ([a4983fe](https://github.com/cortexapps/cli/commit/a4983fe75946c37e2eb582098a21754a10c498c8) by Jeff Schnitter).
- update SKE recipes with GitStateStore, Destination, and git-based resource requests ([8dad6be](https://github.com/cortexapps/cli/commit/8dad6bea12ff52011a2cbe1f15898d2eb91f9ad7) by Jeff Schnitter).
- correct SKE setup — add cert-manager, use latest version, fix integrationAlias ([4e1d2d7](https://github.com/cortexapps/cli/commit/4e1d2d74a096da9d6ff28e4cbedb7c6c50b4d8d6) by Jeff Schnitter).
- indent inline Python in ske-test recipe for just compatibility ([8a57c3c](https://github.com/cortexapps/cli/commit/8a57c3c21a10795baa1a59ca290af14f018ff813) by Jeff Schnitter).

## [1.15.0](https://github.com/cortexapps/cli/releases/tag/1.15.0) - 2026-04-15

<small>[Compare with 1.14.0](https://github.com/cortexapps/cli/compare/1.14.0...1.15.0)</small>
Expand Down
Empty file added cortexapps_cli/__init__.py
Empty file.
66 changes: 66 additions & 0 deletions cortexapps_cli/commands/integrations.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,99 @@
import typer
from typing_extensions import Annotated

import cortexapps_cli.commands.integrations_commands.apiiro as apiiro
import cortexapps_cli.commands.integrations_commands.argocd as argocd
import cortexapps_cli.commands.integrations_commands.aws as aws
import cortexapps_cli.commands.integrations_commands.azure_active_directory as azure_active_directory
import cortexapps_cli.commands.integrations_commands.azure_resources as azure_resources
import cortexapps_cli.commands.integrations_commands.azure_devops as azure_devops
import cortexapps_cli.commands.integrations_commands.bamboohr as bamboohr
import cortexapps_cli.commands.integrations_commands.bitbucket as bitbucket
import cortexapps_cli.commands.integrations_commands.bugsnag as bugsnag
import cortexapps_cli.commands.integrations_commands.buildkite as buildkite
import cortexapps_cli.commands.integrations_commands.checkmarx_sast as checkmarx_sast
import cortexapps_cli.commands.integrations_commands.circleci as circleci
import cortexapps_cli.commands.integrations_commands.clickup as clickup
import cortexapps_cli.commands.integrations_commands.codecov as codecov
import cortexapps_cli.commands.integrations_commands.coralogix as coralogix
import cortexapps_cli.commands.integrations_commands.datadog as datadog
import cortexapps_cli.commands.integrations_commands.dynatrace as dynatrace
import cortexapps_cli.commands.integrations_commands.firehydrant as firehydrant
import cortexapps_cli.commands.integrations_commands.github as github
import cortexapps_cli.commands.integrations_commands.gitlab as gitlab
import cortexapps_cli.commands.integrations_commands.incidentio as incidentio
import cortexapps_cli.commands.integrations_commands.instana as instana
import cortexapps_cli.commands.integrations_commands.jenkins as jenkins
import cortexapps_cli.commands.integrations_commands.jira as jira
import cortexapps_cli.commands.integrations_commands.launchdarkly as launchdarkly
import cortexapps_cli.commands.integrations_commands.mend_sast as mend_sast
import cortexapps_cli.commands.integrations_commands.mend_sca as mend_sca
import cortexapps_cli.commands.integrations_commands.newrelic as newrelic
import cortexapps_cli.commands.integrations_commands.okta as okta
import cortexapps_cli.commands.integrations_commands.opsgenie as opsgenie
import cortexapps_cli.commands.integrations_commands.pagerduty as pagerduty
import cortexapps_cli.commands.integrations_commands.prometheus as prometheus
import cortexapps_cli.commands.integrations_commands.rollbar as rollbar
import cortexapps_cli.commands.integrations_commands.rootly as rootly
import cortexapps_cli.commands.integrations_commands.semgrep as semgrep
import cortexapps_cli.commands.integrations_commands.sentry as sentry
import cortexapps_cli.commands.integrations_commands.servicenow as servicenow
import cortexapps_cli.commands.integrations_commands.servicenow_cloud_observability as servicenow_cloud_observability
import cortexapps_cli.commands.integrations_commands.snyk as snyk
import cortexapps_cli.commands.integrations_commands.sonarqube as sonarqube
import cortexapps_cli.commands.integrations_commands.splunk_observability_cloud as splunk_observability_cloud
import cortexapps_cli.commands.integrations_commands.splunk_on_call as splunk_on_call
import cortexapps_cli.commands.integrations_commands.sumologic as sumologic
import cortexapps_cli.commands.integrations_commands.veracode as veracode
import cortexapps_cli.commands.integrations_commands.wiz as wiz
import cortexapps_cli.commands.integrations_commands.workday as workday
import cortexapps_cli.commands.integrations_commands.xmatters as xmatters

app = typer.Typer(help="Integrations commands", no_args_is_help=True)
app.add_typer(apiiro.app, name="apiiro")
app.add_typer(argocd.app, name="argocd")
app.add_typer(aws.app, name="aws")
app.add_typer(azure_active_directory.app, name="azure-active-directory")
app.add_typer(azure_resources.app, name="azure-resources")
app.add_typer(azure_devops.app, name="azure-devops")
app.add_typer(bamboohr.app, name="bamboohr")
app.add_typer(bitbucket.app, name="bitbucket")
app.add_typer(bugsnag.app, name="bugsnag")
app.add_typer(buildkite.app, name="buildkite")
app.add_typer(checkmarx_sast.app, name="checkmarx-sast")
app.add_typer(circleci.app, name="circleci")
app.add_typer(clickup.app, name="clickup")
app.add_typer(codecov.app, name="codecov")
app.add_typer(coralogix.app, name="coralogix")
app.add_typer(datadog.app, name="datadog")
app.add_typer(dynatrace.app, name="dynatrace")
app.add_typer(firehydrant.app, name="firehydrant")
app.add_typer(github.app, name="github")
app.add_typer(gitlab.app, name="gitlab")
app.add_typer(incidentio.app, name="incidentio")
app.add_typer(instana.app, name="instana")
app.add_typer(jenkins.app, name="jenkins")
app.add_typer(jira.app, name="jira")
app.add_typer(launchdarkly.app, name="launchdarkly")
app.add_typer(mend_sast.app, name="mend-sast")
app.add_typer(mend_sca.app, name="mend-sca")
app.add_typer(newrelic.app, name="newrelic")
app.add_typer(okta.app, name="okta")
app.add_typer(opsgenie.app, name="opsgenie")
app.add_typer(pagerduty.app, name="pagerduty")
app.add_typer(prometheus.app, name="prometheus")
app.add_typer(rollbar.app, name="rollbar")
app.add_typer(rootly.app, name="rootly")
app.add_typer(semgrep.app, name="semgrep")
app.add_typer(sentry.app, name="sentry")
app.add_typer(servicenow.app, name="servicenow")
app.add_typer(servicenow_cloud_observability.app, name="servicenow-cloud-observability")
app.add_typer(snyk.app, name="snyk")
app.add_typer(sonarqube.app, name="sonarqube")
app.add_typer(splunk_observability_cloud.app, name="splunk-observability-cloud")
app.add_typer(splunk_on_call.app, name="splunk-on-call")
app.add_typer(sumologic.app, name="sumo-logic")
app.add_typer(veracode.app, name="veracode")
app.add_typer(wiz.app, name="wiz")
app.add_typer(workday.app, name="workday")
app.add_typer(xmatters.app, name="xmatters")
167 changes: 167 additions & 0 deletions cortexapps_cli/commands/integrations_commands/apiiro.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
import json
from rich import print_json
import typer
from typing_extensions import Annotated

app = typer.Typer(help="Apiiro commands", no_args_is_help=True)

@app.command()
def add(
ctx: typer.Context,
alias: str = typer.Option(..., "--alias", "-a", help="Alias for this configuration"),
api_key: str = typer.Option(..., "--api-key", "-api", help="API key"),
is_default: bool = typer.Option(False, "--is-default", "-i", help="If this is the default configuration"),
file_input: Annotated[typer.FileText, typer.Option("--file", "-f", help="JSON file containing configurations, if command line options not used; can be passed as stdin with -, example: -f-")] = None,
):
"""
Add a single configuration
"""

client = ctx.obj["client"]

if file_input:
if alias or api_key or is_default:
raise typer.BadParameter("When providing a configuration file, do not specify any other attributes")
data = json.loads("".join([line for line in file_input]))
else:
data = {
"alias": alias,
"apiKey": api_key,
"isDefault": is_default,
}

# remove any data elements that are None
data = {k: v for k, v in data.items() if v is not None}

r = client.post("api/v1/apiiro/configuration", data=data)
print_json(data=r)

@app.command()
def add_multiple(
ctx: typer.Context,
file_input: Annotated[typer.FileText, typer.Option("--file", "-f", help="JSON file containing configurations; can be passed as stdin with -, example: -f-")] = None,
):
"""
Add multiple configurations
"""

client = ctx.obj["client"]

data = json.loads("".join([line for line in file_input]))

r = client.put("api/v1/apiiro/configurations", data=data)
print_json(data=r)

@app.command()
def delete(
ctx: typer.Context,
alias: str = typer.Option(..., "--alias", "-a", help="The alias of the configuration"),
):
"""
Delete a configuration
"""

client = ctx.obj["client"]

r = client.delete("api/v1/apiiro/configuration/" + alias)
print_json(data=r)

@app.command()
def delete_all(
ctx: typer.Context,
):
"""
Delete all configurations
"""

client = ctx.obj["client"]

r = client.delete("api/v1/apiiro/configurations")
print_json(data=r)

@app.command()
def get(
ctx: typer.Context,
alias: str = typer.Option(..., "--alias", "-a", help="The alias of the configuration"),
):
"""
Get a configuration
"""

client = ctx.obj["client"]

r = client.get("api/v1/apiiro/configuration/" + alias)
print_json(data=r)

@app.command()
def list(
ctx: typer.Context,
):
"""
Get all configurations
"""

client = ctx.obj["client"]

r = client.get("api/v1/apiiro/configurations")
print_json(data=r)

@app.command()
def get_default(
ctx: typer.Context,
):
"""
Get default configuration
"""

client = ctx.obj["client"]

r = client.get("api/v1/apiiro/default-configuration")
print_json(data=r)

@app.command()
def update(
ctx: typer.Context,
alias: str = typer.Option(..., "--alias", "-a", help="The alias of the configuration"),
is_default: bool = typer.Option(False, "--is-default", "-i", help="If this is the default configuration"),
):
"""
Update a configuration
"""

client = ctx.obj["client"]

data = {
"alias": alias,
"isDefault": is_default
}

r = client.put("api/v1/apiiro/configuration/" + alias, data=data)
print_json(data=r)

@app.command()
def validate(
ctx: typer.Context,
alias: str = typer.Option(..., "--alias", "-a", help="The alias of the configuration"),
):
"""
Validate a configuration
"""

client = ctx.obj["client"]

r = client.post("api/v1/apiiro/configuration/validate/" + alias)
print_json(data=r)

@app.command()
def validate_all(
ctx: typer.Context,
):
"""
Validate all configurations
"""

client = ctx.obj["client"]

r = client.post("api/v1/apiiro/configuration/validate")
print_json(data=r)
Loading