Skip to content

Commit 35b293f

Browse files
committed
Merge branch 'ac8/file-api/connector-builder-support-3' into ac8/file-api/handle-include-files
2 parents 9933a52 + 13fac98 commit 35b293f

38 files changed

+3961
-430
lines changed

.github/workflows/poe-command.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: On-Demand Poe Task
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
comment-id:
7+
description: "Optional comment-id of the slash command. Ignore if not applicable."
8+
required: false
9+
pr:
10+
description: "PR Number"
11+
required: false
12+
13+
permissions:
14+
contents: write
15+
pull-requests: write
16+
17+
jobs:
18+
run-poe-command:
19+
env:
20+
GCP_GSM_CREDENTIALS: ${{ secrets.GCP_GSM_CREDENTIALS }}
21+
runs-on: ubuntu-latest
22+
steps:
23+
- name: Run Poe Slash Command Processor
24+
uses: aaronsteers/poe-command-processor@v1
25+
with:
26+
pr: ${{ github.event.inputs.pr }}
27+
comment-id: ${{ github.event.inputs.comment-id }}
28+
github-token: ${{ secrets.GH_PAT_MAINTENANCE_OCTAVIA }}

.github/workflows/slash_command_dispatch.yml

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ on:
66

77
jobs:
88
slashCommandDispatch:
9-
# Only allow slash commands on pull request (not on issues)
10-
if: ${{ github.event.issue.pull_request }}
119
runs-on: ubuntu-24.04
1210
steps:
1311
- name: Slash Command Dispatch
@@ -19,17 +17,25 @@ jobs:
1917
repository: ${{ github.repository }}
2018
token: ${{ secrets.GH_PAT_MAINTENANCE_OCTAVIA }}
2119
dispatch-type: workflow
22-
issue-type: pull-request
20+
issue-type: both
21+
22+
# Only run for users with 'write' permission on the main repository
23+
permission: write
24+
2325
commands: |
2426
autofix
2527
test
2628
poetry-lock
29+
poe
30+
31+
# Notes regarding static-args:
32+
# - Slash commands can be invoked from both issues and comments.
33+
# - If the slash command is invoked from an issue, we intentionally pass 'null' as the PR number.
34+
# - Comment ID will always be sent, and this is sufficient to post back status updates to the originating comment.
2735
static-args: |
28-
pr=${{ github.event.issue.number }}
36+
pr=${{ github.event.issue.pull_request != null && github.event.issue.number || '' }}
2937
comment-id=${{ github.event.comment.id }}
3038
31-
# Only run for users with 'write' permission on the main repository
32-
permission: write
3339
3440
- name: Edit comment with error message
3541
if: steps.dispatch.outputs.error-message

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@ dist
1515
.idea
1616
.vscode
1717
**/__pycache__
18+
.tmp

airbyte_cdk/cli/__init__.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,9 @@
1-
# Copyright (c) 2024 Airbyte, Inc., all rights reserved.
1+
# Copyright (c) 2025 Airbyte, Inc., all rights reserved.
2+
"""The `airbyte-cdk.cli` module provides command-line interfaces for the Airbyte CDK.
3+
4+
As of now, it includes the following CLI entry points:
5+
6+
- `airbyte-cdk`: Commands for working with connectors.
7+
- `source-declarative-manifest`: Directly invoke the declarative manifests connector.
8+
9+
"""
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# Copyright (c) 2025 Airbyte, Inc., all rights reserved.
2+
"""CLI commands for `airbyte-cdk`.
3+
4+
This CLI interface allows you to interact with your connector, including
5+
testing and running commands.
6+
7+
**Basic Usage:**
8+
9+
```bash
10+
airbyte-cdk --help
11+
airbyte-cdk --version
12+
airbyte-cdk connector --help
13+
airbyte-cdk manifest --help
14+
```
15+
16+
**Running Statelessly:**
17+
18+
You can run the latest version of this CLI, from any machine, using `pipx` or `uvx`:
19+
20+
```bash
21+
# Run the latest version of the CLI:
22+
pipx run airbyte-cdk connector --help
23+
uvx airbyte-cdk connector --help
24+
25+
# Run from a specific CDK version:
26+
pipx run airbyte-cdk==6.5.1 connector --help
27+
uvx airbyte-cdk==6.5.1 connector --help
28+
```
29+
30+
**Running within your virtualenv:**
31+
32+
You can also run from your connector's virtualenv:
33+
34+
```bash
35+
poetry run airbyte-cdk connector --help
36+
```
37+
38+
"""
39+
40+
from typing import cast
41+
42+
import rich_click as click
43+
44+
from airbyte_cdk.cli.airbyte_cdk._connector import connector_cli_group
45+
from airbyte_cdk.cli.airbyte_cdk._image import image_cli_group
46+
from airbyte_cdk.cli.airbyte_cdk._manifest import manifest_cli_group
47+
from airbyte_cdk.cli.airbyte_cdk._secrets import secrets_cli_group
48+
from airbyte_cdk.cli.airbyte_cdk._version import print_version
49+
50+
51+
@click.group(
52+
help=__doc__.replace("\n", "\n\n"), # Render docstring as help text (markdown)
53+
invoke_without_command=True,
54+
)
55+
@click.option(
56+
"--version",
57+
is_flag=True,
58+
help="Show the version of the Airbyte CDK.",
59+
)
60+
@click.pass_context
61+
def cli(
62+
ctx: click.Context,
63+
version: bool,
64+
) -> None:
65+
"""Airbyte CDK CLI.
66+
67+
Help text is provided from the file-level docstring.
68+
"""
69+
if version:
70+
print_version(short=False)
71+
ctx.exit()
72+
73+
if ctx.invoked_subcommand is None:
74+
# If no subcommand is provided, show the help message.
75+
click.echo(ctx.get_help())
76+
ctx.exit()
77+
78+
79+
cli.add_command(connector_cli_group)
80+
cli.add_command(manifest_cli_group)
81+
cli.add_command(image_cli_group)
82+
cli.add_command(secrets_cli_group)
83+
84+
85+
if __name__ == "__main__":
86+
cli()
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
# Copyright (c) 2025 Airbyte, Inc., all rights reserved.
2+
"""CLI command for `airbyte-cdk`."""
3+
4+
USAGE = """CLI command for `airbyte-cdk`.
5+
6+
This CLI interface allows you to interact with your connector, including
7+
testing and running commands.
8+
9+
**Basic Usage:**
10+
11+
```bash
12+
airbyte-cdk --help
13+
airbyte-cdk connector --help
14+
airbyte-cdk manifest --help
15+
```
16+
17+
**Running Statelessly:**
18+
19+
You can run the latest version of this CLI, from any machine, using `pipx` or `uvx`:
20+
21+
```bash
22+
# Run the latest version of the CLI:
23+
pipx run airbyte-cdk connector --help
24+
uvx airbyte-cdk connector --help
25+
26+
# Run from a specific CDK version:
27+
pipx run airbyte-cdk==6.5.1 connector --help
28+
uvx airbyte-cdk==6.5.1 connector --help
29+
```
30+
31+
**Running within your virtualenv:**
32+
33+
You can also run from your connector's virtualenv:
34+
35+
```bash
36+
poetry run airbyte-cdk connector --help
37+
```
38+
39+
"""
40+
41+
import os
42+
from pathlib import Path
43+
from types import ModuleType
44+
45+
import rich_click as click
46+
47+
# from airbyte_cdk.test.standard_tests import pytest_hooks
48+
from airbyte_cdk.cli.airbyte_cdk._util import resolve_connector_name_and_directory
49+
from airbyte_cdk.test.standard_tests.test_resources import find_connector_root_from_name
50+
from airbyte_cdk.test.standard_tests.util import create_connector_test_suite
51+
52+
click.rich_click.TEXT_MARKUP = "markdown"
53+
54+
pytest: ModuleType | None
55+
try:
56+
import pytest
57+
except ImportError:
58+
pytest = None
59+
# Handle the case where pytest is not installed.
60+
# This prevents import errors when running the script without pytest installed.
61+
# We will raise an error later if pytest is required for a given command.
62+
63+
64+
TEST_FILE_TEMPLATE = '''
65+
# Copyright (c) 2025 Airbyte, Inc., all rights reserved.
66+
"""FAST Airbyte Standard Tests for the source_pokeapi_w_components source."""
67+
68+
#from airbyte_cdk.test.standard_tests import {base_class_name}
69+
from airbyte_cdk.test.standard_tests.util import create_connector_test_suite
70+
from pathlib import Path
71+
72+
pytest_plugins = [
73+
"airbyte_cdk.test.standard_tests.pytest_hooks",
74+
]
75+
76+
TestSuite = create_connector_test_suite(
77+
connector_directory=Path(),
78+
)
79+
80+
# class TestSuite({base_class_name}):
81+
# """Test suite for the source_pokeapi_w_components source.
82+
83+
# This class inherits from SourceTestSuiteBase and implements all of the tests in the suite.
84+
85+
# As long as the class name starts with "Test", pytest will automatically discover and run the
86+
# tests in this class.
87+
# """
88+
'''
89+
90+
91+
@click.group(
92+
name="connector",
93+
help=__doc__.replace("\n", "\n\n"), # Render docstring as help text (markdown)
94+
)
95+
def connector_cli_group() -> None:
96+
"""Connector related commands."""
97+
pass
98+
99+
100+
@connector_cli_group.command()
101+
@click.option(
102+
"--connector-name",
103+
type=str,
104+
help="Name of the connector to test. Ignored if --connector-directory is provided.",
105+
)
106+
@click.option(
107+
"--connector-directory",
108+
type=click.Path(exists=True, file_okay=False, path_type=Path),
109+
help="Path to the connector directory.",
110+
)
111+
@click.option(
112+
"--collect-only",
113+
is_flag=True,
114+
default=False,
115+
help="Only collect tests, do not run them.",
116+
)
117+
def test(
118+
connector_name: str | None = None,
119+
connector_directory: Path | None = None,
120+
*,
121+
collect_only: bool = False,
122+
) -> None:
123+
"""Run connector tests.
124+
125+
This command runs the standard connector tests for a specific connector.
126+
127+
If no connector name or directory is provided, we will look within the current working
128+
directory. If the current working directory is not a connector directory (e.g. starting
129+
with 'source-') and no connector name or path is provided, the process will fail.
130+
"""
131+
if pytest is None:
132+
raise ImportError(
133+
"pytest is not installed. Please install pytest to run the connector tests."
134+
)
135+
click.echo("Connector test command executed.")
136+
connector_name, connector_directory = resolve_connector_name_and_directory(
137+
connector_name=connector_name,
138+
connector_directory=connector_directory,
139+
)
140+
141+
connector_test_suite = create_connector_test_suite(
142+
connector_name=connector_name if not connector_directory else None,
143+
connector_directory=connector_directory,
144+
)
145+
146+
pytest_args: list[str] = []
147+
if connector_directory:
148+
pytest_args.append(f"--rootdir={connector_directory}")
149+
os.chdir(str(connector_directory))
150+
else:
151+
print("No connector directory provided. Running tests in the current directory.")
152+
153+
file_text = TEST_FILE_TEMPLATE.format(
154+
base_class_name=connector_test_suite.__bases__[0].__name__,
155+
connector_directory=str(connector_directory),
156+
)
157+
test_file_path = Path() / ".tmp" / "integration_tests/test_airbyte_standards.py"
158+
test_file_path = test_file_path.resolve().absolute()
159+
test_file_path.parent.mkdir(parents=True, exist_ok=True)
160+
test_file_path.write_text(file_text)
161+
162+
if collect_only:
163+
pytest_args.append("--collect-only")
164+
165+
pytest_args.append(str(test_file_path))
166+
click.echo(f"Running tests from connector directory: {connector_directory}...")
167+
click.echo(f"Test file: {test_file_path}")
168+
click.echo(f"Collect only: {collect_only}")
169+
click.echo(f"Pytest args: {pytest_args}")
170+
click.echo("Invoking Pytest...")
171+
pytest.main(
172+
pytest_args,
173+
plugins=[],
174+
)
175+
176+
177+
__all__ = [
178+
"connector_cli_group",
179+
]

0 commit comments

Comments
 (0)