Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Commit

Permalink
Merge pull request #1 from PrefectHQ/renames
Browse files Browse the repository at this point in the history
Align with `prefect-github`
  • Loading branch information
desertaxle authored Nov 3, 2022
2 parents 09f5c6a + b1be6cd commit 183eb7b
Show file tree
Hide file tree
Showing 14 changed files with 96 additions and 51 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- `GitLabRepository` block - [#1](https://github.com/PrefectHQ/prefect-gitlab)
- `GitLabCredentials` block - [#1](https://github.com/PrefectHQ/prefect-gitlab)

### Changed

### Deprecated
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ pip install prefect-gitlab
Then, register to [view the storage block](https://orion-docs.prefect.io/ui/blocks/) on Prefect Cloud:

```bash
prefect block register -m prefect_gitlab.filesystems
prefect block register -m prefect_gitlab
```

Note, to use the `load` method on Blocks, you must already have a block document [saved through code](https://orion-docs.prefect.io/concepts/blocks/#saving-blocks) or [saved through the UI](https://orion-docs.prefect.io/ui/blocks/).
Expand All @@ -51,10 +51,10 @@ Note, to use the `load` method on Blocks, you must already have a block document
### In Python

```python
from prefect_gitlab.filesystems import GitLab
from prefect_gitlab import GitLabRepository

# public GitLab repository
public_gitlab_block = GitLab(
public_gitlab_block = GitLabRepository(
name="my-gitlab-block",
repository="https://gitlab.com/testing/my-repository.git"
)
Expand All @@ -63,7 +63,7 @@ public_gitlab_block.save()


# specific branch or tag of a GitLab repository
branch_gitlab_block = GitLab(
branch_gitlab_block = GitLabRepository(
name="my-gitlab-block",
reference="branch-or-tag-name"
repository="https://gitlab.com/testing/my-repository.git"
Expand All @@ -73,7 +73,7 @@ branch_gitlab_block.save()


# private GitLab repository
private_gitlab_block = GitLab(
private_gitlab_block = GitLabRepository(
name="my-private-gitlab-block",
repository="https://gitlab.com/testing/my-repository.git",
access_token="YOUR_GITLAB_PERSONAL_ACCESS_TOKEN"
Expand Down
2 changes: 1 addition & 1 deletion docs/filesystems.md → docs/credentials.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ description:
notes: This documentation page is generated from source file docstrings.
---

::: prefect_gitlab.filesystems
::: prefect_gitlab.credentials
Binary file removed docs/img/add-gitlab-block.png
Binary file not shown.
Binary file added docs/img/create-gitlab-credentials.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/img/create-gitlab-repository.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed docs/img/gitlab-block-form.png
Binary file not shown.
Binary file added docs/img/gitlab-blocks.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 1 addition & 2 deletions docs/flows.md → docs/repositories.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
---
description:
notes: This documentation page is generated from source file docstrings.
---

::: prefect_gitlab.flows
::: prefect_gitlab.repositories
3 changes: 2 additions & 1 deletion mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,6 @@ watch:

nav:
- Home: index.md
- File Systems: filesystems.md
- Credentials: credentials.md
- Repositories: repositories.md

4 changes: 3 additions & 1 deletion prefect_gitlab/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from . import _version
from .filesystems import GitLab # noqa
from .credentials import GitLabCredentials
from .repositories import GitLabRepository

__version__ = _version.get_versions()["version"]
__all__ = ["GitLabRepository", "GitLabCredentials"]
33 changes: 33 additions & 0 deletions prefect_gitlab/credentials.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
"""Module used to enable authenticated interactions with GitLab"""

from prefect.blocks.core import Block
from pydantic import Field, HttpUrl, SecretStr


class GitLabCredentials(Block):
"""
Store a GitLab personal access token to interact with private GitLab
repositories.
Attributes:
token: The token to authenticate into GitLab.
Examples:
Load stored GitLab credentials:
```python
from prefect_gitlab import GitLabCredentials
gitlab_credentials_block = GitLabCredentials.load("BLOCK_NAME")
```
"""

_block_type_name = "GitLab Credentials"
_logo_url = HttpUrl(
url="https://images.ctfassets.net/gm98wzqotmnx/55edIimT4g9gbjhkh5a3Sp/dfdb9391d8f45c2e93e72e3a4d350771/gitlab-logo-500.png?h=250", # noqa
scheme="https",
)

token: SecretStr = Field(
name="Personal Access Token",
default=None,
description="A GitLab Personal Access Token with repo scope.",
)
42 changes: 24 additions & 18 deletions prefect_gitlab/filesystems.py → prefect_gitlab/repositories.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
The `GitLab` class in this collection is a storage block that lets Prefect agents
pull Prefect flow code from GitLab repositories.
The `GitLab` block is ideally configured via the Prefect UI, but can also be used
The `GitLab` block is ideally configured via the Prefect UI, but can also be used
in Python as the following examples demonstrate.
Examples:
```python
from prefect_gitlab.filesystems import GitLab
from prefect_gitlab.repositories import GitLabRepository
# public GitLab repository
public_gitlab_block = GitLab(
public_gitlab_block = GitLabRepository(
name="my-gitlab-block",
repository="https://gitlab.com/testing/my-repository.git"
)
Expand All @@ -21,7 +21,7 @@
# specific branch or tag of a GitLab repository
branch_gitlab_block = GitLab(
branch_gitlab_block = GitLabRepository(
name="my-gitlab-block",
reference="branch-or-tag-name"
repository="https://gitlab.com/testing/my-repository.git"
Expand All @@ -31,7 +31,7 @@
# private GitLab repository
private_gitlab_block = GitLab(
private_gitlab_block = GitLabRepository(
name="my-private-gitlab-block",
repository="https://gitlab.com/testing/my-repository.git",
access_token="YOUR_GITLAB_PERSONAL_ACCESS_TOKEN"
Expand All @@ -51,19 +51,25 @@
from prefect.filesystems import ReadableDeploymentStorage
from prefect.utilities.asyncutils import sync_compatible
from prefect.utilities.processutils import run_process
from pydantic import Field, HttpUrl, SecretStr, validator
from pydantic import Field, HttpUrl, validator

from prefect_gitlab.credentials import GitLabCredentials

class GitLab(ReadableDeploymentStorage):

class GitLabRepository(ReadableDeploymentStorage):
"""
Interact with files stored in GitLab repositories.
An accessible installation of git is required for this block to function
properly.
"""

_block_type_name = "GitLab"
_block_type_name = "GitLab Repository"
_logo_url = HttpUrl(
url="https://images.ctfassets.net/gm98wzqotmnx/55edIimT4g9gbjhkh5a3Sp/dfdb9391d8f45c2e93e72e3a4d350771/gitlab-logo-500.png?h=250", # noqa
scheme="https",
)
_description = "Interact with files stored in GitLab repositories."

repository: str = Field(
default=...,
Expand All @@ -75,13 +81,13 @@ class GitLab(ReadableDeploymentStorage):
default=None,
description="An optional reference to pin to; can be a branch name or tag.",
)
access_token: Optional[SecretStr] = Field(
name="Personal Access Token",
credentials: Optional[GitLabCredentials] = Field(
default=None,
description="A GitLab Personal Access Token (PAT) with repo scope.",
description="An optional GitLab Credentials block for authenticating with "
"private GitLab repos.",
)

@validator("access_token")
@validator("credentials")
def _ensure_credentials_go_with_https(cls, v: str, values: dict) -> str:
"""Ensure that credentials are not provided with 'SSH' formatted GitLub URLs.
Note: validates `access_token` specifically so that it only fires when
Expand All @@ -91,7 +97,7 @@ def _ensure_credentials_go_with_https(cls, v: str, values: dict) -> str:
if urllib.parse.urlparse(values["repository"]).scheme != "https":
raise InvalidRepositoryURLError(
(
"Crendentials can only be used with GitHub repositories "
"Credentials can only be used with GitLab repositories "
"using the 'HTTPS' format. You must either remove the "
"credential if you wish to use the 'SSH' format and are not "
"using a private repository, or you must change the repository "
Expand All @@ -103,12 +109,12 @@ def _ensure_credentials_go_with_https(cls, v: str, values: dict) -> str:

def _create_repo_url(self) -> str:
"""Format the URL provided to the `git clone` command.
For private repos: https://<oauth-key>@github.com/<username>/<repo>.git
For private repos: https://<oauth-key>@gitlab.com/<username>/<repo>.git
All other repos should be the same as `self.repository`.
"""
url_components = urllib.parse.urlparse(self.repository)
if url_components.scheme == "https" and self.access_token is not None:
token = self.access_token.get_secret_value()
if url_components.scheme == "https" and self.credentials is not None:
token = self.credentials.token.get_secret_value()
updated_components = url_components._replace(
netloc=f"oauth2:{token}@{url_components.netloc}"
)
Expand All @@ -122,7 +128,7 @@ def _create_repo_url(self) -> str:
def _get_paths(
dst_dir: Union[str, None], src_dir: str, sub_directory: Optional[str]
) -> Tuple[str, str]:
"""Returns the fully formed paths for GitHubRepository contents in the form
"""Returns the fully formed paths for GitLabRepository contents in the form
(content_source, content_destination).
"""
if dst_dir is None:
Expand All @@ -143,7 +149,7 @@ async def get_directory(
self, from_path: Optional[str] = None, local_path: Optional[str] = None
) -> None:
"""
Clones a GitHub project specified in `from_path` to the provided `local_path`;
Clones a GitLab project specified in `from_path` to the provided `local_path`;
defaults to cloning the repository reference configured on the Block to the
present working directory.
Args:
Expand Down
47 changes: 24 additions & 23 deletions tests/test_filesystems.py → tests/test_repositories.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
from pydantic import SecretStr

import prefect_gitlab
from prefect_gitlab.filesystems import GitLab
from prefect_gitlab.credentials import GitLabCredentials
from prefect_gitlab.repositories import GitLabRepository


class TestGitLab:
Expand Down Expand Up @@ -58,7 +59,7 @@ def __exit__(self, *args, **kwargs):
pass

async def test_subprocess_errors_are_surfaced(self):
g = GitLab(repository="incorrect-url-scheme")
g = GitLabRepository(repository="incorrect-url-scheme")
with pytest.raises(
OSError, match="fatal: repository 'incorrect-url-scheme' does not exist"
):
Expand All @@ -69,8 +70,8 @@ class p:
returncode = 0

mock = AsyncMock(return_value=p())
monkeypatch.setattr(prefect_gitlab.filesystems, "run_process", mock)
g = GitLab(repository="prefect")
monkeypatch.setattr(prefect_gitlab.repositories, "run_process", mock)
g = GitLabRepository(repository="prefect")
await g.get_directory()

assert mock.await_count == 1
Expand All @@ -82,27 +83,27 @@ class p:
returncode = 0

mock = AsyncMock(return_value=p())
monkeypatch.setattr(prefect_gitlab.filesystems, "run_process", mock)
g = GitLab(repository="prefect", reference="2.0.0")
monkeypatch.setattr(prefect_gitlab.repositories, "run_process", mock)
g = GitLabRepository(repository="prefect", reference="2.0.0")
await g.get_directory()

assert mock.await_count == 1
expected_cmd = ["git", "clone", "prefect", "-b", "2.0.0", "--depth", "1"]
assert mock.await_args[0][0][: len(expected_cmd)] == expected_cmd

async def test_token_added_correctly_from_credential(self, monkeypatch):
"""Ensure that the repo url is in the format `https://<oauth-key>@github.com/<username>/<repo>.git`.""" # noqa: E501
"""Ensure that the repo url is in the format `https://<oauth-key>@gitlab.com/<username>/<repo>.git`.""" # noqa: E501

class p:
returncode = 0

mock = AsyncMock(return_value=p())
monkeypatch.setattr(prefect_gitlab.filesystems, "run_process", mock)
monkeypatch.setattr(prefect_gitlab.repositories, "run_process", mock)
credential = "XYZ"
repo = "https://gitlab.com/PrefectHQ/prefect.git"
g = GitLab(
g = GitLabRepository(
repository=repo,
access_token=SecretStr(credential),
credentials=GitLabCredentials(token=SecretStr(credential)),
)
await g.get_directory()
assert mock.await_count == 1
Expand All @@ -124,19 +125,19 @@ class p:
returncode = 0

mock = AsyncMock(return_value=p())
monkeypatch.setattr(prefect_gitlab.filesystems, "run_process", mock)
monkeypatch.setattr(prefect_gitlab.repositories, "run_process", mock)
credential = "XYZ"
error_msg = (
"Crendentials can only be used with GitHub repositories "
"Credentials can only be used with GitLab repositories "
"using the 'HTTPS' format. You must either remove the "
"credential if you wish to use the 'SSH' format and are not "
"using a private repository, or you must change the repository "
"URL to the 'HTTPS' format."
)
with pytest.raises(InvalidRepositoryURLError, match=error_msg):
GitLab(
repository="git@github.com:PrefectHQ/prefect.git",
access_token=SecretStr(credential),
GitLabRepository(
repository="git@gitlab.com:PrefectHQ/prefect.git",
credentials=GitLabCredentials(token=SecretStr(credential)),
)

async def test_dir_contents_copied_correctly_with_get_directory(
Expand All @@ -148,7 +149,7 @@ class p:
returncode = 0

mock = AsyncMock(return_value=p())
monkeypatch.setattr(prefect_gitlab.filesystems, "run_process", mock)
monkeypatch.setattr(prefect_gitlab.repositories, "run_process", mock)

sub_dir_name = "puppy"

Expand All @@ -161,13 +162,13 @@ class p:
# move file contents to tmp_dst
with TemporaryDirectory() as tmp_dst:
monkeypatch.setattr(
prefect_gitlab.filesystems,
prefect_gitlab.repositories,
"TemporaryDirectory",
self.MockTmpDir,
)

g = GitLab(
repository="https://github.com/PrefectHQ/prefect.git",
g = GitLabRepository(
repository="https://gitlab.com/PrefectHQ/prefect.git",
)
await g.get_directory(local_path=tmp_dst)

Expand All @@ -187,7 +188,7 @@ class p:
returncode = 0

mock = AsyncMock(return_value=p())
monkeypatch.setattr(prefect_gitlab.filesystems, "run_process", mock)
monkeypatch.setattr(prefect_gitlab.repositories, "run_process", mock)

sub_dir_name = "puppy"

Expand All @@ -200,13 +201,13 @@ class p:
# move file contents to tmp_dst
with TemporaryDirectory() as tmp_dst:
monkeypatch.setattr(
prefect_gitlab.filesystems,
prefect_gitlab.repositories,
"TemporaryDirectory",
self.MockTmpDir,
)

g = GitLab(
repository="https://github.com/PrefectHQ/prefect.git",
g = GitLabRepository(
repository="https://gitlab.com/PrefectHQ/prefect.git",
)
await g.get_directory(local_path=tmp_dst, from_path=sub_dir_name)

Expand Down

0 comments on commit 183eb7b

Please sign in to comment.