-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
airbyte-ci: Add upgrade cdk command #33313
Merged
Merged
Changes from 22 commits
Commits
Show all changes
26 commits
Select commit
Hold shift + click to select a range
1b984f1
source defined primary key
7b39d11
update docusaurus
806e26f
remove unrelated changes
6624da4
remove unrelated changes
ee847f0
Merge branch 'master' into flash1293/update-docusaurus
7d2f58d
Merge remote-tracking branch 'origin/master' into flash1293/update-do…
5564fc8
cleanup
b8aec3a
Merge branch 'master' into flash1293/update-docusaurus
0d42b01
Merge branch 'master' into flash1293/update-docusaurus
da6d1d2
Merge branch 'master' into flash1293/update-docusaurus
ee7ef31
add upgrade CDK command
46b76eb
Merge remote-tracking branch 'origin/master' into flash1293/upgrade-c…
2a30eb0
Merge remote-tracking branch 'origin/master' into flash1293/upgrade-c…
867e427
try to run only step
c77890e
remove
64324a1
Merge remote-tracking branch 'origin/master' into flash1293/upgrade-c…
84c0662
review comments and tests
d499e9f
format
9528948
update readme
f75f2a1
Merge branch 'master' into flash1293/upgrade-cdk-command
0ad032f
Merge remote-tracking branch 'origin/master' into flash1293/upgrade-c…
006a010
review comments
6341690
Merge remote-tracking branch 'origin/master' into flash1293/upgrade-c…
cb7adf3
review comments
f3a3d89
Merge remote-tracking branch 'origin/master' into flash1293/upgrade-c…
6dba66f
bump airbyte-ci version
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3 changes: 3 additions & 0 deletions
3
airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/upgrade_cdk/__init__.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# | ||
# Copyright (c) 2023 Airbyte, Inc., all rights reserved. | ||
# |
67 changes: 67 additions & 0 deletions
67
airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/upgrade_cdk/commands.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
# | ||
# Copyright (c) 2023 Airbyte, Inc., all rights reserved. | ||
# | ||
|
||
import asyncclick as click | ||
import requests | ||
from pipelines.airbyte_ci.connectors.context import ConnectorContext | ||
from pipelines.airbyte_ci.connectors.pipeline import run_connectors_pipelines | ||
from pipelines.airbyte_ci.connectors.upgrade_cdk.pipeline import run_connector_cdk_upgrade_pipeline | ||
from pipelines.cli.dagger_pipeline_command import DaggerPipelineCommand | ||
|
||
|
||
def latest_cdk_version(): | ||
""" | ||
Get the latest version of airbyte-cdk from pypi | ||
""" | ||
cdk_pypi_url = "https://pypi.org/pypi/airbyte-cdk/json" | ||
response = requests.get(cdk_pypi_url) | ||
response.raise_for_status() | ||
package_info = response.json() | ||
return package_info["info"]["version"] | ||
|
||
|
||
@click.command(cls=DaggerPipelineCommand, short_help="Upgrade CDK version") | ||
@click.argument("target-cdk-version", type=str, default=latest_cdk_version) | ||
@click.pass_context | ||
async def bump_version( | ||
ctx: click.Context, | ||
target_cdk_version: str, | ||
) -> bool: | ||
"""Upgrade CDK version""" | ||
|
||
connectors_contexts = [ | ||
ConnectorContext( | ||
pipeline_name=f"Upgrade CDK version of connector {connector.technical_name}", | ||
connector=connector, | ||
is_local=ctx.obj["is_local"], | ||
git_branch=ctx.obj["git_branch"], | ||
git_revision=ctx.obj["git_revision"], | ||
ci_report_bucket=ctx.obj["ci_report_bucket_name"], | ||
report_output_prefix=ctx.obj["report_output_prefix"], | ||
use_remote_secrets=ctx.obj["use_remote_secrets"], | ||
gha_workflow_run_url=ctx.obj.get("gha_workflow_run_url"), | ||
dagger_logs_url=ctx.obj.get("dagger_logs_url"), | ||
pipeline_start_timestamp=ctx.obj.get("pipeline_start_timestamp"), | ||
ci_context=ctx.obj.get("ci_context"), | ||
ci_gcs_credentials=ctx.obj["ci_gcs_credentials"], | ||
ci_git_user=ctx.obj["ci_git_user"], | ||
ci_github_access_token=ctx.obj["ci_github_access_token"], | ||
enable_report_auto_open=False, | ||
s3_build_cache_access_key_id=ctx.obj.get("s3_build_cache_access_key_id"), | ||
s3_build_cache_secret_key=ctx.obj.get("s3_build_cache_secret_key"), | ||
) | ||
for connector in ctx.obj["selected_connectors_with_modified_files"] | ||
] | ||
|
||
await run_connectors_pipelines( | ||
connectors_contexts, | ||
run_connector_cdk_upgrade_pipeline, | ||
"Upgrade CDK version pipeline", | ||
ctx.obj["concurrency"], | ||
ctx.obj["dagger_logs_path"], | ||
ctx.obj["execute_timeout"], | ||
target_cdk_version, | ||
) | ||
|
||
return True |
91 changes: 91 additions & 0 deletions
91
airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/upgrade_cdk/pipeline.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
# | ||
# Copyright (c) 2023 Airbyte, Inc., all rights reserved. | ||
# | ||
|
||
import os | ||
import re | ||
|
||
from pipelines.airbyte_ci.connectors.context import ConnectorContext | ||
from pipelines.airbyte_ci.connectors.reports import ConnectorReport | ||
from pipelines.helpers import git | ||
from pipelines.models.steps import Step, StepResult, StepStatus | ||
|
||
|
||
class SetCDKVersion(Step): | ||
title = "Set CDK Version" | ||
|
||
def __init__( | ||
self, | ||
context: ConnectorContext, | ||
new_version: str, | ||
): | ||
super().__init__(context) | ||
self.new_version = new_version | ||
|
||
async def _run(self) -> StepResult: | ||
context: ConnectorContext = self.context | ||
og_connector_dir = await context.get_connector_dir() | ||
if not "setup.py" in await og_connector_dir.entries(): | ||
return StepResult( | ||
self, | ||
StepStatus.FAILURE, | ||
stdout="Connector does not have a setup.py file.", | ||
) | ||
setup_py = og_connector_dir.file("setup.py") | ||
setup_py_content = await setup_py.contents() | ||
try: | ||
updated_setup_py = self.update_cdk_version(setup_py_content) | ||
updated_connector_dir = og_connector_dir.with_new_file("setup.py", updated_setup_py) | ||
diff = og_connector_dir.diff(updated_connector_dir) | ||
exported_successfully = await diff.export(os.path.join(git.get_git_repo_path(), context.connector.code_directory)) | ||
if not exported_successfully: | ||
return StepResult( | ||
self, | ||
StepStatus.FAILURE, | ||
stdout="Could not export diff to local git repo.", | ||
) | ||
return StepResult(self, StepStatus.SUCCESS, stdout=f"Updated CDK version to {self.new_version}", output_artifact=diff) | ||
except ValueError as e: | ||
return StepResult( | ||
self, | ||
StepStatus.FAILURE, | ||
stderr=f"Could not set CDK version: {e}", | ||
exc_info=e, | ||
) | ||
|
||
def update_cdk_version(self, og_setup_py_content: str) -> str: | ||
alafanechere marked this conversation as resolved.
Show resolved
Hide resolved
|
||
airbyte_cdk_dependency = re.search( | ||
r"airbyte-cdk(?P<extra>\[[a-zA-Z0-9-]*\])?(?P<version>[<>=!~]+[0-9]*\.[0-9]*\.[0-9]*)?", og_setup_py_content | ||
) | ||
# If there is no airbyte-cdk dependency, add the version | ||
if airbyte_cdk_dependency is not None: | ||
new_version = f"airbyte-cdk{airbyte_cdk_dependency.group('extra') or ''}>={self.new_version}" | ||
return og_setup_py_content.replace(airbyte_cdk_dependency.group(), new_version) | ||
else: | ||
raise ValueError("Could not find airbyte-cdk dependency in setup.py") | ||
|
||
|
||
async def run_connector_cdk_upgrade_pipeline( | ||
context: ConnectorContext, | ||
semaphore, | ||
target_version: str, | ||
) -> ConnectorReport: | ||
"""Run a pipeline to upgrade the CDK version for a single connector. | ||
|
||
Args: | ||
context (ConnectorContext): The initialized connector context. | ||
|
||
Returns: | ||
ConnectorReport: The reports holding the CDK version set results. | ||
""" | ||
async with semaphore: | ||
steps_results = [] | ||
async with context: | ||
set_cdk_version = SetCDKVersion( | ||
context, | ||
target_version, | ||
) | ||
set_cdk_version_result = await set_cdk_version.run() | ||
steps_results.append(set_cdk_version_result) | ||
context.report = ConnectorReport(context, steps_results, name="CONNECTOR VERSION CDK UPGRADE RESULTS") | ||
return context.report |
121 changes: 121 additions & 0 deletions
121
airbyte-ci/connectors/pipelines/tests/test_upgrade_cdk.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
# | ||
# Copyright (c) 2023 Airbyte, Inc., all rights reserved. | ||
# | ||
|
||
import json | ||
import random | ||
from pathlib import Path | ||
from typing import List | ||
from unittest.mock import AsyncMock, MagicMock | ||
|
||
import anyio | ||
import pytest | ||
from connector_ops.utils import Connector, ConnectorLanguage | ||
from dagger import Directory | ||
from pipelines.airbyte_ci.connectors.context import ConnectorContext | ||
from pipelines.airbyte_ci.connectors.publish import pipeline as publish_pipeline | ||
from pipelines.airbyte_ci.connectors.upgrade_cdk import pipeline as upgrade_cdk_pipeline | ||
from pipelines.models.steps import StepStatus | ||
|
||
pytestmark = [ | ||
pytest.mark.anyio, | ||
] | ||
|
||
|
||
@pytest.fixture | ||
def sample_connector(): | ||
return Connector("source-pokeapi") | ||
|
||
|
||
def get_sample_setup_py(airbyte_cdk_dependency: str): | ||
return f"""from setuptools import find_packages, setup | ||
|
||
MAIN_REQUIREMENTS = [ | ||
"{airbyte_cdk_dependency}", | ||
] | ||
|
||
setup( | ||
name="source_pokeapi", | ||
description="Source implementation for Pokeapi.", | ||
author="Airbyte", | ||
author_email="contact@airbyte.io", | ||
packages=find_packages(), | ||
install_requires=MAIN_REQUIREMENTS, | ||
) | ||
""" | ||
|
||
|
||
@pytest.fixture | ||
def connector_context(sample_connector, dagger_client, current_platform): | ||
context = ConnectorContext( | ||
pipeline_name="test", | ||
connector=sample_connector, | ||
git_branch="test", | ||
git_revision="test", | ||
report_output_prefix="test", | ||
is_local=True, | ||
use_remote_secrets=True, | ||
targeted_platforms=[current_platform], | ||
) | ||
context.dagger_client = dagger_client | ||
return context | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"setup_py_content, expected_setup_py_content", | ||
[ | ||
(get_sample_setup_py("airbyte-cdk"), get_sample_setup_py("airbyte-cdk>=6.6.6")), | ||
(get_sample_setup_py("airbyte-cdk[file-based]"), get_sample_setup_py("airbyte-cdk[file-based]>=6.6.6")), | ||
(get_sample_setup_py("airbyte-cdk==1.2.3"), get_sample_setup_py("airbyte-cdk>=6.6.6")), | ||
(get_sample_setup_py("airbyte-cdk>=1.2.3"), get_sample_setup_py("airbyte-cdk>=6.6.6")), | ||
(get_sample_setup_py("airbyte-cdk[file-based]>=1.2.3"), get_sample_setup_py("airbyte-cdk[file-based]>=6.6.6")), | ||
], | ||
) | ||
async def test_run_connector_cdk_upgrade_pipeline( | ||
connector_context: ConnectorContext, setup_py_content: str, expected_setup_py_content: str | ||
): | ||
full_og_connector_dir = await connector_context.get_connector_dir() | ||
updated_connector_dir = full_og_connector_dir.with_new_file("setup.py", setup_py_content) | ||
|
||
# For this test, replace the actual connector dir with an updated version that sets the setup.py contents | ||
connector_context.get_connector_dir = AsyncMock(return_value=updated_connector_dir) | ||
|
||
# Mock the diff method to record the resulting directory and return a mock to not actually export the diff to the repo | ||
alafanechere marked this conversation as resolved.
Show resolved
Hide resolved
|
||
updated_connector_dir.diff = MagicMock(return_value=AsyncMock()) | ||
step = upgrade_cdk_pipeline.SetCDKVersion(connector_context, "6.6.6") | ||
alafanechere marked this conversation as resolved.
Show resolved
Hide resolved
|
||
step_result = await step.run() | ||
assert step_result.status == StepStatus.SUCCESS | ||
|
||
# Check that the resulting directory that got passed to the mocked diff method looks as expected | ||
resulting_directory: Directory = await full_og_connector_dir.diff(updated_connector_dir.diff.call_args[0][0]) | ||
files = await resulting_directory.entries() | ||
# validate only setup.py is changed | ||
assert files == ["setup.py"] | ||
setup_py = resulting_directory.file("setup.py") | ||
actual_setup_py_content = await setup_py.contents() | ||
assert expected_setup_py_content == actual_setup_py_content | ||
|
||
# Assert that the diff was exported to the repo | ||
assert updated_connector_dir.diff.return_value.export.call_count == 1 | ||
|
||
|
||
async def test_fail_connector_cdk_upgrade_pipeline_on_missing_setup_py(connector_context: ConnectorContext): | ||
full_og_connector_dir = await connector_context.get_connector_dir() | ||
updated_connector_dir = full_og_connector_dir.without_file("setup.py") | ||
|
||
connector_context.get_connector_dir = AsyncMock(return_value=updated_connector_dir) | ||
|
||
step = upgrade_cdk_pipeline.SetCDKVersion(connector_context, "6.6.6") | ||
step_result = await step.run() | ||
assert step_result.status == StepStatus.FAILURE | ||
|
||
|
||
async def test_fail_connector_cdk_upgrade_pipeline_on_missing_airbyte_cdk(connector_context: ConnectorContext): | ||
full_og_connector_dir = await connector_context.get_connector_dir() | ||
updated_connector_dir = full_og_connector_dir.with_new_file("setup.py", get_sample_setup_py("another-lib==1.2.3")) | ||
|
||
connector_context.get_connector_dir = AsyncMock(return_value=updated_connector_dir) | ||
|
||
step = upgrade_cdk_pipeline.SetCDKVersion(connector_context, "6.6.6") | ||
step_result = await step.run() | ||
assert step_result.status == StepStatus.FAILURE |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we return
self.skip(reason="Connector is not a Python connector")
when the connector is a Java connector?