Create a custom action
Great Expectations provides Actions for common workflows, such as sending emails and Microsoft Teams notifications. If these don't meet your needs, you can create a custom Action to integrate with different tools, such as Atlassian Jira, or apply custom business logic based on Validation Results. Example use cases for custom Actions include:
- Opening tickets in an issue tracker when Validation runs fail.
- Triggering different webhooks depending on which Expectations fail.
- Running follow-up ETL jobs to fill in missing values.
A custom Action can do anything that can be done with Python code.
To create a custom Action, you subclass the ValidationAction class, overriding the type attribute with a unique name and the run() method with custom logic.
Prerequisites
Procedure
- Instructions
- Sample code
-
Create a new custom Action class that inherits the
ValidationActionclass.Pythonclass MyCustomAction(ValidationAction): -
Set a unique name for
type.Pythontype: Literal["my_custom_cloud_action"] = "my_custom_cloud_action" -
Optional. Add any additional fields your Action requires at runtime. Actions are built on Pydantic models. Define the field name as a class-level attribute on your Action, and annotate it with the correct type. When you instantiate the Action, pass the field value into the Action
initmethod. Your Action will have access to these values within your customrunmethod throughself.<MY_FIELD_NAME>. The example below shows how to include fields for accessing a Jira API.Pythonmy_custom_str_field: str
jira_api_url: str
jira_project_key: str -
Override the
run()method with the logic for the Action. The example below shows how to create a Jira ticket using the additional fields you added in the previous step.Python@override
def run(
self,
checkpoint_result: CheckpointResult,
action_context: Union[
ActionContext, None
], # Contains results from prior Actions in the same Checkpoint run.
) -> dict:
# Domain-specific logic
self._do_my_custom_action(checkpoint_result)
# Optional. Access custom fields you provide the Action at runtime.
extra_context = self.my_custom_str_field
jira_api_url = self.jira_api_url
jira_project_key = self.jira_project_key
# Return information about the Action
return {
"some": "info",
"extra_context": extra_context,
"jira_api_url": jira_api_url,
"jira_project_key": jira_project_key,
}
def _do_my_custom_action(self, checkpoint_result: CheckpointResult):
# Perform custom logic based on the validation results.
# from jira import JIRA
# Replace with your Jira email address and Jira Personal Access Token (PAT)
# jira_email_address = "<your_jira_email_address>"
# pat = "<your-personal-access-token>"
# Create a Jira connection using the JIRA library
# jira = JIRA(server=self.jira_api_url, basic_auth=(jira_email_address, pat))
# Issue data (replace with your own data)
# issue_data = {
# "project": {"key": self.jira_project_key},
# "summary": "New issue created for GX Cloud Validation result",
# "description": "This issue has been created based on the result of a Validation in GX Cloud.",
# "issuetype": {"name": "Task"},
# }
# try:
# new_issue = jira.create_issue(fields=issue_data)
# except Exception as e:
# print("Failed to create issue:", str(e))
...
from typing import Literal, Union
from typing_extensions import override
from great_expectations.checkpoint import (
ActionContext,
CheckpointResult,
ValidationAction,
)
# 1. Extend the `ValidationAction` class.
class MyCustomAction(ValidationAction):
# 2. Set the `type` attribute to a unique string that identifies the Action.
type: Literal["my_custom_cloud_action"] = "my_custom_cloud_action"
# 3. Optional. Add any additional fields your Action requires at runtime.
my_custom_str_field: str
jira_api_url: str
jira_project_key: str
# 4. Override the `run()` method to perform the desired task.
@override
def run(
self,
checkpoint_result: CheckpointResult,
action_context: Union[
ActionContext, None
], # Contains results from prior Actions in the same Checkpoint run.
) -> dict:
# Domain-specific logic
self._do_my_custom_action(checkpoint_result)
# Optional. Access custom fields you provide the Action at runtime.
extra_context = self.my_custom_str_field
jira_api_url = self.jira_api_url
jira_project_key = self.jira_project_key
# Return information about the Action
return {
"some": "info",
"extra_context": extra_context,
"jira_api_url": jira_api_url,
"jira_project_key": jira_project_key,
}
def _do_my_custom_action(self, checkpoint_result: CheckpointResult):
# Perform custom logic based on the validation results.
# from jira import JIRA
# Replace with your Jira email address and Jira Personal Access Token (PAT)
# jira_email_address = "<your_jira_email_address>"
# pat = "<your-personal-access-token>"
# Create a Jira connection using the JIRA library
# jira = JIRA(server=self.jira_api_url, basic_auth=(jira_email_address, pat))
# Issue data (replace with your own data)
# issue_data = {
# "project": {"key": self.jira_project_key},
# "summary": "New issue created for GX Cloud Validation result",
# "description": "This issue has been created based on the result of a Validation in GX Cloud.",
# "issuetype": {"name": "Task"},
# }
# try:
# new_issue = jira.create_issue(fields=issue_data)
# except Exception as e:
# print("Failed to create issue:", str(e))
...
Now you can use your custom Action through the GX Cloud API like you would any built-in Action. Trigger your custom Action to start automating responses to Validation Results.
Limitations
Keep the following limitations in mind when using custom Actions.
- When using a fully-hosted deployment, if you add a custom Action to your GX-managed checkpoint, you will no longer be able to use the Validation schedule or the Validate button in the UI.
- When using an agent-enabled deployment, if you add a custom Action to your GX-managed checkpoint, you will no longer be able to use the Validation schedule or the Validate button in the UI unless you customize the GX Agent image with a command for your custom Action.