diff --git a/.github/workflows/sync-keep-workflows.yml b/.github/workflows/sync-keep-workflows.yml new file mode 100644 index 000000000..2d952a31c --- /dev/null +++ b/.github/workflows/sync-keep-workflows.yml @@ -0,0 +1,34 @@ +# A workflow that sync Keep workflows from a directory + +on: + push: + paths: + - 'examples/workflows/**' + workflow_dispatch: + inputs: + keep_api_key: + description: 'Keep API Key' + required: false + keep_api_url: + description: 'Keep API URL' + required: false + default: 'https://api.keep.dev' + +jobs: + compile: + name: Upload workflows to Keep + runs-on: ubuntu-latest + # Use the Keep CLI image + container: + image: us-central1-docker.pkg.dev/keephq/keep/keep-cli:latest + env: + KEEP_API_KEY: ${{ secrets.KEEP_API_KEY || github.event.inputs.keep_api_key }} + KEEP_API_URL: ${{ secrets.KEEP_API_URL || github.event.inputs.keep_api_url }} + + steps: + - name: Check out the repo + uses: actions/checkout@v2 + + - name: Run Keep CLI + run: | + keep apply -f examples/workflows diff --git a/docker/Dockerfile.cli b/docker/Dockerfile.cli index 5367d7d12..c5632fd21 100644 --- a/docker/Dockerfile.cli +++ b/docker/Dockerfile.cli @@ -23,4 +23,3 @@ FROM base as final ENV PATH="/venv/bin:${PATH}" ENV VIRTUAL_ENV="/venv" COPY --from=builder /venv /venv -ENTRYPOINT ["keep"] diff --git a/keep/cli/cli.py b/keep/cli/cli.py index 9ca4dac99..c5d93cad7 100644 --- a/keep/cli/cli.py +++ b/keep/cli/cli.py @@ -60,6 +60,8 @@ class Info: """An information object to pass data between CLI functions.""" + KEEP_MANAGED_API_URL = "https://api.keephq.dev" + def __init__(self): # Note: This object must have an empty constructor. """Create a new instance.""" self.verbose: int = 0 @@ -81,7 +83,11 @@ def set_config(self, keep_config: str): ) pass self.api_key = self.config.get("api_key") or os.getenv("KEEP_API_KEY") or "" - self.keep_api_url = self.config.get("keep_api_url") or os.getenv("KEEP_API_URL") + self.keep_api_url = ( + self.config.get("keep_api_url") + or os.getenv("KEEP_API_URL") + or Info.KEEP_MANAGED_API_URL + ) if not self.api_key: click.echo( @@ -101,6 +107,13 @@ def set_config(self, keep_config: str): ) sys.exit(2) + click.echo( + click.style( + f"Using keep api url: {self.keep_api_url}", + bold=True, + ) + ) + # pass_info is a decorator for functions that pass 'Info' objects. #: pylint: disable=invalid-name @@ -372,36 +385,54 @@ def list_workflows(info: Info): print(table) +def apply_workflow(file: str, info: Info): + """Helper function to apply a single workflow.""" + with open(file, "rb") as f: + files = {"file": (os.path.basename(file), f)} + workflow_endpoint = info.keep_api_url + "/workflows" + response = requests.post( + workflow_endpoint, + headers={"x-api-key": info.api_key, "accept": "application/json"}, + files=files, + ) + return response + + @workflow.command() @click.option( "--file", "-f", type=click.Path(exists=True), - help="The workflow file", + help="The workflow file or directory containing workflow files", required=True, ) @pass_info def apply(info: Info, file: str): - """Apply a workflow.""" - with open(file, "rb") as f: - files = { - "file": (file.split("/")[-1], f) - } # The field 'file' should match the name in the API endpoint - workflow_endpoint = info.keep_api_url + "/workflows" - response = requests.post( - workflow_endpoint, - headers={"x-api-key": info.api_key, "accept": "application/json"}, - files=files, - ) + """Apply a workflow or multiple workflows from a directory.""" + if os.path.isdir(file): + for filename in os.listdir(file): + if filename.endswith(".yml") or filename.endswith(".yaml"): + click.echo(click.style(f"Applying workflow {filename}", bold=True)) + full_path = os.path.join(file, filename) + response = apply_workflow(full_path, info) + # Handle response for each file + if response.ok: + click.echo( + click.style( + f"Workflow {filename} applied successfully", bold=True + ) + ) + else: + click.echo( + click.style( + f"Error applying workflow {filename}: {response.text}", + bold=True, + ) + ) + else: + response = apply_workflow(file, info) if response.ok: click.echo(click.style(f"Workflow {file} applied successfully", bold=True)) - response = response.json() - click.echo( - click.style(f"Workflow id: {response.get('workflow_id')}", bold=True) - ) - click.echo( - click.style(f"Workflow revision: {response.get('revision')}", bold=True) - ) else: click.echo( click.style(