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
22 changes: 20 additions & 2 deletions Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ pytest := 'PYTHONPATH=. poetry run pytest -rA'
export CORTEX_API_KEY := env('CORTEX_API_KEY')
export CORTEX_BASE_URL := env('CORTEX_BASE_URL', "https://api.getcortexapp.com")
export CORTEX_API_KEY_VIEWER := env('CORTEX_API_KEY_VIEWER')
export GITHUB_TEST_ORG := env('GITHUB_TEST_ORG', "")
export GITHUB_TEST_PAT := env('GITHUB_TEST_PAT', "")
export GITHUB_TEST_USERNAME := env('GITHUB_TEST_USERNAME', "")
export GITHUB_INTEGRATION_ALIAS := env('GITHUB_INTEGRATION_ALIAS', "")
export GITLAB_TOKEN := env('GITLAB_TOKEN', "")
export GITLAB_INTEGRATION_ALIAS := env('GITLAB_INTEGRATION_ALIAS', "")

help:
@just -l
Expand All @@ -13,11 +19,11 @@ _setup:

# Run all tests
test-all: _setup test-import
{{pytest}} -n auto -m "not setup and not perf" --html=report.html --self-contained-html --cov=cortexapps_cli --cov-append --cov-report term-missing tests
{{pytest}} -n auto -m "not setup and not perf and not functional" --html=report.html --self-contained-html --cov=cortexapps_cli --cov-append --cov-report term-missing tests

# Run all tests serially - helpful to see if any tests seem to be hanging
_test-all-individual: test-import
{{pytest}} -m "not setup and not perf" --html=report-all-invidual.html --self-contained-html --cov=cortexapps_cli --cov-append --cov-report term-missing tests
{{pytest}} -m "not setup and not perf and not functional" --html=report-all-invidual.html --self-contained-html --cov=cortexapps_cli --cov-append --cov-report term-missing tests

# Run import test, a pre-requisite for any tests that rely on test data.
test-import:
Expand All @@ -27,6 +33,18 @@ test-import:
test testname:
{{pytest}} -n auto -m "" {{testname}}

# Import functional test data (workflows)
test-functional-import:
{{pytest}} tests/functional/test_functional_import.py --cov=cortexapps_cli --cov-report=

# Run functional tests, ie: just test-functional tests/functional/test_gh_branches.py
test-functional *args:
{{pytest}} -v -s -n auto -m functional --html=report-functional.html --self-contained-html {{args}}

# Clean up orphaned functional test resources from interrupted runs
test-functional-sweep:
{{pytest}} -v -s tests/functional/test_gh_sweep.py

# Run performance tests (rate limiting, long-running tests)
test-perf:
@echo "Running performance tests (this may take 60+ seconds)..."
Expand Down
2 changes: 1 addition & 1 deletion cortexapps_cli/commands/entity_relationships.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from cortexapps_cli.command_options import CommandOptions, ListCommandOptions

app = typer.Typer(
help="Entity Relationships commands (Beta)",
help="Entity Relationships commands",
no_args_is_help=True
)

Expand Down
79 changes: 78 additions & 1 deletion cortexapps_cli/commands/workflows.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import yaml

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

Expand Down Expand Up @@ -142,3 +142,80 @@ def create(
raise typer.BadParameter("Input file is neither valid JSON nor YAML.")

r = client.post("api/v1/workflows", data=data, content_type=content_type)

@app.command()
def run(
ctx: typer.Context,
tag: str = typer.Option(..., "--tag", "-t", help="The tag or unique identifier for the workflow"),
scope: str = typer.Option("GLOBAL", "--scope", "-s", help="Scope type: GLOBAL or ENTITY"),
entity: str = typer.Option(None, "--entity", "-e", help="Entity tag (required when scope is ENTITY)"),
run_as: str = typer.Option(None, "--run-as", help="Email of user to run the workflow as"),
context: str = typer.Option(None, "--context", "-x", help="JSON string for initialContext"),
context_file: Annotated[typer.FileText, typer.Option("--context-file", help="JSON file for initialContext")] = None,
wait: bool = typer.Option(False, "--wait", "-w", help="Poll until the run completes"),
timeout: int = typer.Option(300, "--timeout", help="Max seconds to wait when --wait is used"),
):
"""
(Beta) Run a workflow. API key must have the Run workflows permission.
The workflow must have isRunnableViaApi set to true.
"""
import time as time_module

client = ctx.obj["client"]

# Build scope payload
if scope.upper() == "ENTITY":
if not entity:
raise typer.BadParameter("--entity is required when --scope is ENTITY")
scope_payload = {"type": "ENTITY", "entityId": entity}
else:
scope_payload = {"type": "GLOBAL"}

# Build request body
body = {"scope": scope_payload}

if run_as:
body["runAs"] = run_as

# Handle initialContext from --context or --context-file
if context and context_file:
raise typer.BadParameter("Cannot specify both --context and --context-file")
if context:
body["initialContext"] = json.loads(context)
elif context_file:
body["initialContext"] = json.load(context_file)

r = client.post(f"api/v1/workflows/{tag}/runs", data=body)

if not wait:
print_output(r)
return

# Poll until completed or timeout
run_id = r.get("id")
if not run_id:
print_output(r)
return

start = time_module.time()
while time_module.time() - start < timeout:
time_module.sleep(2)
r = client.get(f"api/v1/workflows/{tag}/runs/{run_id}")
status = r.get("status", "").upper()
if status in ("COMPLETED", "FAILED", "CANCELLED"):
break

print_output(r)

@app.command("get-run")
def get_run(
ctx: typer.Context,
tag: str = typer.Option(..., "--tag", "-t", help="The tag or unique identifier for the workflow"),
run_id: str = typer.Option(..., "--run-id", "-r", help="The run ID"),
):
"""
(Beta) Get details of a workflow run. API key must have the View workflow runs permission.
"""
client = ctx.obj["client"]
r = client.get(f"api/v1/workflows/{tag}/runs/{run_id}")
print_output(r)
Empty file.
27 changes: 27 additions & 0 deletions data/functional/workflows/gh-add-label-to-pull-request.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: "Functional Test: GitHub Add Label to Pull Request"
tag: func-test-gh-add-label-to-pull-request
description: Functional test for the github.addLabelToPullRequest action block
isDraft: false
isRunnableViaApi: true
filter:
type: GLOBAL
variables:
- slug: repo
type: STRING
- slug: pull-number
type: STRING
- slug: label
type: STRING
actions:
- name: Add label to pull request
slug: add-label-to-pull-request
schema:
type: ADVANCED_HTTP_REQUEST
actionIdentifier: github.addLabelToPullRequest
integrationAlias: __GITHUB_INTEGRATION_ALIAS__
inputs:
repo: "{{variables.repo}}"
pull_number: "{{variables.pull-number}}"
label: "{{variables.label}}"
outgoingActions: []
isRootAction: true
24 changes: 24 additions & 0 deletions data/functional/workflows/gh-add-user-to-org.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: "Functional Test: GitHub Add User to Org"
tag: func-test-gh-add-user-to-org
description: Functional test for the github.addUserToOrg action block
isDraft: false
isRunnableViaApi: true
filter:
type: GLOBAL
variables:
- slug: org
type: STRING
- slug: username
type: STRING
actions:
- name: Add user to org
slug: add-user-to-org
schema:
type: ADVANCED_HTTP_REQUEST
actionIdentifier: github.addUserToOrg
integrationAlias: __GITHUB_INTEGRATION_ALIAS__
inputs:
org: "{{variables.org}}"
username: "{{variables.username}}"
outgoingActions: []
isRootAction: true
27 changes: 27 additions & 0 deletions data/functional/workflows/gh-add-user-to-team.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: "Functional Test: GitHub Add User to Team"
tag: func-test-gh-add-user-to-team
description: Functional test for the github.addUserToTeam action block
isDraft: false
isRunnableViaApi: true
filter:
type: GLOBAL
variables:
- slug: org
type: STRING
- slug: team
type: STRING
- slug: username
type: STRING
actions:
- name: Add user to team
slug: add-user-to-team
schema:
type: ADVANCED_HTTP_REQUEST
actionIdentifier: github.addUserToTeam
integrationAlias: __GITHUB_INTEGRATION_ALIAS__
inputs:
org: "{{variables.org}}"
team: "{{variables.team}}"
username: "{{variables.username}}"
outgoingActions: []
isRootAction: true
27 changes: 27 additions & 0 deletions data/functional/workflows/gh-create-branch.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: "Functional Test: GitHub Create Branch"
tag: func-test-gh-create-branch
description: Functional test for the github.createBranch action block
isDraft: false
isRunnableViaApi: true
filter:
type: GLOBAL
variables:
- slug: repo
type: STRING
- slug: new-branch
type: STRING
- slug: sha
type: STRING
actions:
- name: Create branch
slug: create-branch
schema:
type: ADVANCED_HTTP_REQUEST
actionIdentifier: github.createBranch
integrationAlias: __GITHUB_INTEGRATION_ALIAS__
inputs:
repo: "{{variables.repo}}"
new_branch: "{{variables.new-branch}}"
sha: "{{variables.sha}}"
outgoingActions: []
isRootAction: true
24 changes: 24 additions & 0 deletions data/functional/workflows/gh-create-deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: "Functional Test: GitHub Create Deployment"
tag: func-test-gh-create-deployment
description: Functional test for the github.createDeployment action block
isDraft: false
isRunnableViaApi: true
filter:
type: GLOBAL
variables:
- slug: repo
type: STRING
- slug: ref
type: STRING
actions:
- name: Create deployment
slug: create-deployment
schema:
type: ADVANCED_HTTP_REQUEST
actionIdentifier: github.createDeployment
integrationAlias: __GITHUB_INTEGRATION_ALIAS__
inputs:
repo: "{{variables.repo}}"
ref: "{{variables.ref}}"
outgoingActions: []
isRootAction: true
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: "Functional Test: GitHub Create or Update Custom Property Values"
tag: func-test-gh-create-or-update-custom-property-values
description: Functional test for the github.createOrUpdateCustomPropertyValues action block
isDraft: false
isRunnableViaApi: true
filter:
type: GLOBAL
variables:
- slug: repo
type: STRING
- slug: properties
type: STRING
actions:
- name: Create or update custom property values
slug: create-or-update-custom-property-values
schema:
type: ADVANCED_HTTP_REQUEST
actionIdentifier: github.createOrUpdateCustomPropertyValues
integrationAlias: __GITHUB_INTEGRATION_ALIAS__
inputs:
repo: "{{variables.repo}}"
properties: "{{{variables.properties}}}"
outgoingActions: []
isRootAction: true
33 changes: 33 additions & 0 deletions data/functional/workflows/gh-create-or-update-file.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: "Functional Test: GitHub Create or Update File"
tag: func-test-gh-create-or-update-file
description: Functional test for the GitHub create or update file action block
isDraft: false
isRunnableViaApi: true
filter:
type: GLOBAL
variables:
- slug: repo
type: STRING
- slug: commit-message
type: STRING
- slug: content
type: STRING
- slug: path
type: STRING
- slug: branch
type: STRING
actions:
- name: Create or update file
slug: create-or-update-file
schema:
type: GITHUB_CREATE_OR_UPDATE_FILE
alias: __GITHUB_INTEGRATION_ALIAS__
repositoryName: "{{variables.repo}}"
commitMessage: "{{variables.commit-message}}"
content: "{{variables.content}}"
path: "{{variables.path}}"
branch: "{{variables.branch}}"
committer: null
author: null
outgoingActions: []
isRootAction: true
27 changes: 27 additions & 0 deletions data/functional/workflows/gh-create-pull-request-comment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: "Functional Test: GitHub Create Pull Request Comment"
tag: func-test-gh-create-pull-request-comment
description: Functional test for the github.createPullRequestComment action block
isDraft: false
isRunnableViaApi: true
filter:
type: GLOBAL
variables:
- slug: repo
type: STRING
- slug: pull-number
type: STRING
- slug: body
type: STRING
actions:
- name: Create pull request comment
slug: create-pull-request-comment
schema:
type: ADVANCED_HTTP_REQUEST
actionIdentifier: github.createPullRequestComment
integrationAlias: __GITHUB_INTEGRATION_ALIAS__
inputs:
repo: "{{variables.repo}}"
pull_number: "{{variables.pull-number}}"
body: "{{variables.body}}"
outgoingActions: []
isRootAction: true
30 changes: 30 additions & 0 deletions data/functional/workflows/gh-create-pull-request.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: "Functional Test: GitHub Create Pull Request"
tag: func-test-gh-create-pull-request
description: Functional test for the github.createPullRequest action block
isDraft: false
isRunnableViaApi: true
filter:
type: GLOBAL
variables:
- slug: repo
type: STRING
- slug: title
type: STRING
- slug: head
type: STRING
- slug: base
type: STRING
actions:
- name: Create pull request
slug: create-pull-request
schema:
type: ADVANCED_HTTP_REQUEST
actionIdentifier: github.createPullRequest
integrationAlias: __GITHUB_INTEGRATION_ALIAS__
inputs:
repo: "{{variables.repo}}"
title: "{{variables.title}}"
head: "{{variables.head}}"
base: "{{variables.base}}"
outgoingActions: []
isRootAction: true
Loading