Skip to content

Commit

Permalink
[airbyte-ci/auto-merge] - Updates PR pipeline to bypass CI checks for…
Browse files Browse the repository at this point in the history
… promoted release candidate PRs (#49827)
  • Loading branch information
pnilan authored Jan 9, 2025
1 parent 809936f commit 4265fab
Show file tree
Hide file tree
Showing 11 changed files with 103 additions and 34 deletions.
3 changes: 3 additions & 0 deletions airbyte-ci/connectors/auto_merge/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ have been merged.

## Changelog

### 0.1.3
Adds `auto-merge/bypass-ci-checks` label which does not require CI checks to pass to auto-merge PR.

### 0.1.2
Set merge method to `squash`.

Expand Down
2 changes: 1 addition & 1 deletion airbyte-ci/connectors/auto_merge/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "auto-merge"
version = "0.1.2"
version = "0.1.3"
description = ""
authors = ["Airbyte <[email protected]>"]
readme = "README.md"
Expand Down
1 change: 1 addition & 0 deletions airbyte-ci/connectors/auto_merge/src/auto_merge/consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

AIRBYTE_REPO = "airbytehq/airbyte"
AUTO_MERGE_LABEL = "auto-merge"
AUTO_MERGE_BYPASS_CI_CHECKS_LABEL = "auto-merge/bypass-ci-checks"
BASE_BRANCH = "master"
CONNECTOR_PATH_PREFIXES = {
"airbyte-integrations/connectors",
Expand Down
27 changes: 23 additions & 4 deletions airbyte-ci/connectors/auto_merge/src/auto_merge/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@
from collections.abc import Iterator
from contextlib import contextmanager
from pathlib import Path
from typing import TYPE_CHECKING, Optional
from typing import TYPE_CHECKING, Callable, Optional

from github import Auth, Github

from .consts import AIRBYTE_REPO, AUTO_MERGE_LABEL, BASE_BRANCH, MERGE_METHOD
from .consts import AIRBYTE_REPO, AUTO_MERGE_BYPASS_CI_CHECKS_LABEL, AUTO_MERGE_LABEL, BASE_BRANCH, MERGE_METHOD
from .env import GITHUB_TOKEN, PRODUCTION
from .helpers import generate_job_summary_as_markdown
from .pr_validators import ENABLED_VALIDATORS
from .pr_validators import VALIDATOR_MAPPING

if TYPE_CHECKING:
from github.Commit import Commit as GithubCommit
Expand Down Expand Up @@ -49,7 +49,9 @@ def check_if_pr_is_auto_mergeable(head_commit: GithubCommit, pr: PullRequest, re
Returns:
bool: True if the PR is auto-mergeable, False otherwise
"""
for validator in ENABLED_VALIDATORS:

validators = get_pr_validators(pr)
for validator in validators:
is_valid, error = validator(head_commit, pr, required_checks)
if not is_valid:
if error:
Expand All @@ -58,6 +60,23 @@ def check_if_pr_is_auto_mergeable(head_commit: GithubCommit, pr: PullRequest, re
return True


def get_pr_validators(pr: PullRequest) -> set[Callable]:
"""
Get the validator for a PR based on its labels
Args:
pr (PullRequest): The PR to get the validator for
Returns:
list[callable]: The validators
"""

for label in pr.labels:
if label.name in VALIDATOR_MAPPING:
return VALIDATOR_MAPPING[label.name]
return VALIDATOR_MAPPING[AUTO_MERGE_LABEL]


def merge_with_retries(pr: PullRequest, max_retries: int = 3, wait_time: int = 60) -> Optional[PullRequest]:
"""Merge a PR with retries
Expand Down
25 changes: 21 additions & 4 deletions airbyte-ci/connectors/auto_merge/src/auto_merge/pr_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

from __future__ import annotations

from typing import TYPE_CHECKING, Optional, Tuple
from typing import TYPE_CHECKING, Callable, Optional, Tuple

from .consts import AUTO_MERGE_LABEL, BASE_BRANCH, CONNECTOR_PATH_PREFIXES
from .consts import AUTO_MERGE_BYPASS_CI_CHECKS_LABEL, AUTO_MERGE_LABEL, BASE_BRANCH, CONNECTOR_PATH_PREFIXES

if TYPE_CHECKING:
from github.Commit import Commit as GithubCommit
Expand All @@ -18,6 +18,15 @@ def has_auto_merge_label(head_commit: GithubCommit, pr: PullRequest, required_ch
return True, None


def has_auto_merge_bypass_ci_checks_label(
head_commit: GithubCommit, pr: PullRequest, required_checks: set[str]
) -> Tuple[bool, Optional[str]]:
has_auto_merge_bypass_ci_checks_label = any(label.name == AUTO_MERGE_BYPASS_CI_CHECKS_LABEL for label in pr.labels)
if not has_auto_merge_bypass_ci_checks_label:
return False, f"does not have the {AUTO_MERGE_BYPASS_CI_CHECKS_LABEL} label"
return True, None


def targets_main_branch(head_commit: GithubCommit, pr: PullRequest, required_checks: set[str]) -> Tuple[bool, Optional[str]]:
if not pr.base.ref == BASE_BRANCH:
return False, f"does not target {BASE_BRANCH}"
Expand Down Expand Up @@ -55,5 +64,13 @@ def head_commit_passes_all_required_checks(
# - the head commit passes all required checks

# PLEASE BE CAREFUL OF THE VALIDATOR ORDERING
# Let's declared faster checks first as the check_if_pr_is_auto_mergeable function fails fast.
ENABLED_VALIDATORS = [has_auto_merge_label, targets_main_branch, only_modifies_connectors, head_commit_passes_all_required_checks]
# Let's declare faster checks first as the check_if_pr_is_auto_mergeable function fails fast.
COMMON_VALIDATORS = {
targets_main_branch,
only_modifies_connectors,
}
# Let's declare faster checks first as the check_if_pr_is_auto_mergeable function fails fast.
VALIDATOR_MAPPING: dict[str, set[Callable]] = {
AUTO_MERGE_LABEL: COMMON_VALIDATORS | {has_auto_merge_label, head_commit_passes_all_required_checks},
AUTO_MERGE_BYPASS_CI_CHECKS_LABEL: COMMON_VALIDATORS | {has_auto_merge_bypass_ci_checks_label},
}
3 changes: 2 additions & 1 deletion airbyte-ci/connectors/pipelines/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -853,7 +853,8 @@ airbyte-ci connectors --language=low-code migrate-to-manifest-only
## Changelog

| Version | PR | Description |
|---------|------------------------------------------------------------| ---------------------------------------------------------------------------------------------------------------------------- |
| ------- | ---------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| 4.48.5 | [#49827](https://github.com/airbytehq/airbyte/pull/49827) | Bypasses CI checks for promoted release candidate PRs. |
| 4.48.4 | [#51003](https://github.com/airbytehq/airbyte/pull/51003) | Install git in the build / test connector container when `--use-cdk-ref` is passed. |
| 4.48.3 | [#50988](https://github.com/airbytehq/airbyte/pull/50988) | Remove deprecated `--no-update` flag from poetry commands |
| 4.48.2 | [#50871](https://github.com/airbytehq/airbyte/pull/50871) | Speed up connector modification detection. |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import semver
import yaml
from airbyte_protocol.models.airbyte_protocol import ConnectorSpecification # type: ignore
from auto_merge.consts import AUTO_MERGE_BYPASS_CI_CHECKS_LABEL # type: ignore
from connector_ops.utils import METADATA_FILE_NAME, ConnectorLanguage # type: ignore
from dagger import Container, Directory, ExecError, File, ImageLayerCompression, Platform, QueryError
from pydantic import BaseModel, ValidationError
Expand Down Expand Up @@ -753,7 +754,9 @@ async def run_connector_promote_pipeline(context: PublishConnectorContext, semap
all_modified_files.update(
await add_changelog_entry.export_modified_files(context.connector.local_connector_documentation_directory)
)
post_changelog_pr_update = CreateOrUpdatePullRequest(context, skip_ci=False, labels=["auto-merge"])
post_changelog_pr_update = CreateOrUpdatePullRequest(
context, skip_ci=True, labels=[AUTO_MERGE_BYPASS_CI_CHECKS_LABEL, "promoted-rc"]
)
pr_creation_args, pr_creation_kwargs = get_promotion_pr_creation_arguments(
all_modified_files, context, results, current_version, promoted_version
)
Expand Down
4 changes: 2 additions & 2 deletions airbyte-ci/connectors/pipelines/pipelines/helpers/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@
from pathlib import Path
from typing import TYPE_CHECKING

import anyio
import asyncclick as click
import asyncer
from dagger import Client, Config, Container, Directory, ExecError, File, ImageLayerCompression, Platform, Secret
from exceptiongroup import ExceptionGroup
from more_itertools import chunked

if TYPE_CHECKING:
Expand Down Expand Up @@ -115,7 +115,7 @@ async def get_file_contents(container: Container, path: str) -> Optional[str]:
def catch_exec_error_group() -> Generator:
try:
yield
except anyio.ExceptionGroup as eg:
except ExceptionGroup as eg:
for e in eg.exceptions:
if isinstance(e, ExecError):
raise e
Expand Down
50 changes: 34 additions & 16 deletions airbyte-ci/connectors/pipelines/poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions airbyte-ci/connectors/pipelines/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ build-backend = "poetry.core.masonry.api"

[tool.poetry]
name = "pipelines"
version = "4.48.4"
version = "4.48.5"
description = "Packaged maintained by the connector operations team to perform CI for connectors' pipelines"
authors = ["Airbyte <[email protected]>"]

[tool.poetry.dependencies]
python = "~3.10"
dagger-io = "==0.13.3"
beartype = ">=0.18.2"
asyncer = "^0.0.2"
anyio = "^3.4.1"
asyncer = "^0"
anyio = "^4"
more-itertools = "^8.11.0"
docker = "^7"
semver = "^3"
Expand All @@ -40,6 +40,7 @@ pygithub = "^2.3.0"
pydash = "6.0.2"
python-slugify = ">=8.0.4"
deepdiff = "^7.0.1"
auto-merge = { path = "../auto_merge", develop = true }

[tool.poetry.group.dev.dependencies]
freezegun = "^1.2.2"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import anyio
import pytest
from exceptiongroup import ExceptionGroup

from pipelines.helpers.execution.run_steps import InvalidStepConfiguration, RunStepOptions, StepToRun, run_steps
from pipelines.models.contexts.pipeline_context import PipelineContext
Expand Down Expand Up @@ -353,17 +354,22 @@ async def test_run_steps_throws_on_invalid_args(invalid_args):
[StepToRun(id="step1", step=TestStep(test_context), args=invalid_args)],
]

with pytest.raises(TypeError):
with pytest.raises(ExceptionGroup) as exc:
await run_steps(steps)

assert len(exc.value.exceptions) == 1
assert isinstance(exc.value.exceptions[0], TypeError)


@pytest.mark.anyio
async def test_run_steps_with_params():
steps = [StepToRun(id="step1", step=TestStep(test_context))]
options = RunStepOptions(fail_fast=True, step_params={"step1": {"--param1": ["value1"]}})
TestStep.accept_extra_params = False
with pytest.raises(ValueError):
with pytest.raises(ExceptionGroup) as exc:
await run_steps(steps, options=options)
assert len(exc.value.exceptions) == 1
assert isinstance(exc.value.exceptions[0], ValueError)
assert steps[0].step.params_as_cli_options == []
TestStep.accept_extra_params = True
await run_steps(steps, options=options)
Expand Down

0 comments on commit 4265fab

Please sign in to comment.