Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## [1.7.4]

### Enhancements

- **feat(PLU-441): ready the GitHub source connector for Foundation.** Adds OAuth support (`oauth_token`/`refresh_token` alongside the existing PAT, refresh handled upstream per PLU-381) and emits the git blob SHA as `metadata.version` for incremental change detection. Indexing fetches the repo once per run instead of twice per file, falls back to a per-directory walk when GitHub truncates the recursive tree, and skips empty files, directories, and submodules. Fixes downloads failing with `FileNotFoundError` on nested paths. GitHub API errors are classified consistently (auth → `UserAuthError`, throttle → `RateLimitError`, 5xx → `ProviderError`), and transient throttles / 5xx / network errors are retried with exponential backoff that honors GitHub's `Retry-After` (`max_retries`, default 10).

## [1.7.3]

### Fixes
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ dropbox = ["dropboxdrivefs", "fsspec"]
duckdb = ["pandas", "duckdb"]
elasticsearch = ["elasticsearch[async]<9.0.0"]
gcs = ["gcsfs", "fsspec", "beautifulsoup4"]
github = ["pygithub>1.58.0", "requests"]
github = ["pygithub>1.58.0", "requests", "tenacity"]
gitlab = ["python-gitlab"]
google-drive = ["google-api-python-client", "tenacity"]
hubspot = ["hubspot-api-client", "urllib3"]
Expand Down
37 changes: 27 additions & 10 deletions test/integration/connectors/test_github.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,7 @@
)


@pytest.mark.tags(CONNECTOR_TYPE, SOURCE_TAG, UNCATEGORIZED_TAG)
@pytest.mark.asyncio
@requires_env("GH_READ_ONLY_ACCESS_TOKEN")
async def test_github_source(temp_dir):
access_token = os.environ["GH_READ_ONLY_ACCESS_TOKEN"]
connection_config = GithubConnectionConfig(
access_config=GithubAccessConfig(access_token=access_token),
url="dcneiner/Downloadify",
)

async def _validate_github_source(connection_config: GithubConnectionConfig, temp_dir):
indexer = GithubIndexer(
connection_config=connection_config,
index_config=GithubIndexerConfig(file_glob=["*.txt", "*.html"]),
Expand All @@ -52,3 +43,29 @@ async def test_github_source(temp_dir):
postdownload_file_data_check=source_filedata_display_name_set_check,
),
)


@pytest.mark.tags(CONNECTOR_TYPE, SOURCE_TAG, UNCATEGORIZED_TAG)
@pytest.mark.asyncio
@requires_env("GH_READ_ONLY_ACCESS_TOKEN")
async def test_github_source(temp_dir):
access_token = os.environ["GH_READ_ONLY_ACCESS_TOKEN"]
connection_config = GithubConnectionConfig(
access_config=GithubAccessConfig(access_token=access_token),
url="dcneiner/Downloadify",
)
await _validate_github_source(connection_config, temp_dir)


@pytest.mark.tags(CONNECTOR_TYPE, SOURCE_TAG, UNCATEGORIZED_TAG)
@pytest.mark.asyncio
@requires_env("GH_OAUTH_ACCESS_TOKEN")
async def test_github_source_oauth(temp_dir):
# The platform's init-oauth-refresh container populates oauth_token with a fresh access
# token before each run; here we supply an already-valid OAuth token to exercise the path.
oauth_token = os.environ["GH_OAUTH_ACCESS_TOKEN"]
connection_config = GithubConnectionConfig(
access_config=GithubAccessConfig(oauth_token=oauth_token),
url="dcneiner/Downloadify",
)
await _validate_github_source(connection_config, temp_dir)
Loading
Loading