Skip to content
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

Add documentation publish and preview workflows #42

Merged
merged 18 commits into from
Feb 17, 2024
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
38 changes: 38 additions & 0 deletions .github/workflows/pydoc_preview.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Test Docs Generation

on:
push:
branches:
- main
pull_request: {}


jobs:
preview_docs:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Poetry
uses: Gr1N/setup-poetry@v8
with:
poetry-version: "1.7.1"
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.10'
cache: 'poetry'

- name: Install dependencies
run: poetry install

- name: Generate documentation
run: |
poetry run generate-docs

- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
# Upload entire repository
path: 'docs/generated'
60 changes: 60 additions & 0 deletions .github/workflows/pydoc_publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: Publish Documentation Site

on:
push:
branches:
- main

# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:

# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write

# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
group: "pages"
cancel-in-progress: false

jobs:
publish_docs:
runs-on: ubuntu-latest
environment:
name: "github-pages"
url: ${{ steps.deployment.outputs.page_url }}

steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Poetry
uses: Gr1N/setup-poetry@v8
with:
poetry-version: "1.7.1"
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.10'
cache: 'poetry'
- name: Setup Pages
uses: actions/configure-pages@v4

- name: Install dependencies
run: poetry install

- name: Generate documentation
run: |
poetry run generate-docs

- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
# Upload entire repository
path: 'docs/generated'

- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
35 changes: 35 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Contributing to PyAirbyte

Learn how you can become a contributor to PyAirbyte.

## Development

- Make sure [Poetry is installed](https://python-poetry.org/docs/#).
- Run `poetry install`
- For examples, check out the `examples` folder. They can be run via `poetry run python examples/<example file>`
- Unit tests and type checks can be run via `poetry run pytest`

## Documentation

Regular documentation lives in the `/docs` folder. Based on the doc strings of public methods, we generate API documentation using [pdoc](https://pdoc.dev).

To generate the documentation, run:

```console
poetry run generate-docs
```

The `generate-docs` CLI command is mapped to the `run()` function of `docs/generate.py`.

Documentation pages will be generated in the `docs/generated` folder. The `test_docs.py` test in pytest will automatically update generated content. This updates must be manually committed before docs tests will pass.

## Release

- In your PR:
- Bump the version in `pyproject.toml`
- Add a changelog entry to the table below
- Once the PR is merged, go to Github and trigger the `Publish PyAirbyte Manually` workflow. This will publish the new version to PyPI.

## Versioning

Versioning follows [Semantic Versioning](https://semver.org/). For new features, bump the minor version. For bug fixes, bump the patch version. For pre-releases, append `dev.N` to the version. For example, `0.1.0dev.1` is the first pre-release of the `0.1.0` version.
47 changes: 14 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,36 +1,22 @@
# PyAirbyte

PyAirbyte is a library that allows to run Airbyte syncs embedded into any Python application, without the need to run Airbyte server.

## Development

- Make sure [Poetry is installed](https://python-poetry.org/docs/#).
- Run `poetry install`
- For examples, check out the `examples` folder. They can be run via `poetry run python examples/<example file>`
- Unit tests and type checks can be run via `poetry run pytest`

## Release

- In your PR:
- Bump the version in `pyproject.toml`
- Add a changelog entry to the table below
- Once the PR is merged, go to Github and trigger the `Publish AirbyteLib Manually` workflow. This will publish the new version to PyPI.
PyAirbyte is a library that allows to run Airbyte syncs embedded into any Python application, without requiring connectivity to a hosted Airbyte instance.

## Secrets Management

AirbyteLib can auto-import secrets from the following sources:
PyAirbyte can auto-import secrets from the following sources:

1. Environment variables.
2. Variables defined in a local `.env` ("Dotenv") file.
3. [Google Colab secrets](https://medium.com/@parthdasawant/how-to-use-secrets-in-google-colab-450c38e3ec75).
4. Manual entry via [`getpass`](https://docs.python.org/3.9/library/getpass.html).

_Note: Additional secret store options may be supported in the future. [More info here.](https://github.com/airbytehq/PyAirbyte-private-beta/discussions/5)_
_Note: Additional secret store options may be supported in the future. [More info here.](https://github.com/airbytehq/airbyte-lib-private-beta/discussions/5)_

### Retrieving Secrets

```python
from airbyte import get_secret, SecretSource
from airbyte_lib import get_secret, SecretSource

source = get_connection("source-github")
source.set_config(
Expand All @@ -40,26 +26,17 @@ source.set_config(
)
```

The `get_secret()` function accepts an optional `source` argument of enum type `SecretSource`. If omitted or set to `SecretSource.ANY`, AirbyteLib will search all available secrets sources. If `source` is set to a specific source, then only that source will be checked. If a list of `SecretSource` entries is passed, then the sources will be checked using the provided ordering.

By default, AirbyteLib will prompt the user for any requested secrets that are not provided via other secret managers. You can disable this prompt by passing `prompt=False` to `get_secret()`.

### Versioning
The `get_secret()` function accepts an optional `source` argument of enum type `SecretSource`. If omitted or set to `SecretSource.ANY`, PyAirbyte will search all available secrets sources. If `source` is set to a specific source, then only that source will be checked. If a list of `SecretSource` entries is passed, then the sources will be checked using the provided ordering.

Versioning follows [Semantic Versioning](https://semver.org/). For new features, bump the minor version. For bug fixes, bump the patch version. For pre-releases, append `dev.N` to the version. For example, `0.1.0dev.1` is the first pre-release of the `0.1.0` version.

## Documentation

Regular documentation lives in the `/docs` folder. Based on the doc strings of public methods, we generate API documentation using [pdoc](https://pdoc.dev). To generate the documentation, run `poetry run generate-docs`. The documentation will be generated in the `docs/generate` folder. This needs to be done manually when changing the public interface of the library.

A unit test validates the documentation is up to date.
By default, PyAirbyte will prompt the user for any requested secrets that are not provided via other secret managers. You can disable this prompt by passing `prompt=False` to `get_secret()`.

## Connector compatibility

To make a connector compatible with PyAirbyte, the following requirements must be met:
* The connector must be a Python package, with a `pyproject.toml` or a `setup.py` file.
* In the package, there must be a `run.py` file that contains a `run` method. This method should read arguments from the command line, and run the connector with them, outputting messages to stdout.
* The `pyproject.toml` or `setup.py` file must specify a command line entry point for the `run` method called `source-<connector name>`. This is usually done by adding a `console_scripts` section to the `pyproject.toml` file, or a `entry_points` section to the `setup.py` file. For example:

- The connector must be a Python package, with a `pyproject.toml` or a `setup.py` file.
- In the package, there must be a `run.py` file that contains a `run` method. This method should read arguments from the command line, and run the connector with them, outputting messages to stdout.
- The `pyproject.toml` or `setup.py` file must specify a command line entry point for the `run` method called `source-<connector name>`. This is usually done by adding a `console_scripts` section to the `pyproject.toml` file, or a `entry_points` section to the `setup.py` file. For example:

```toml
[tool.poetry.scripts]
Expand Down Expand Up @@ -101,6 +78,10 @@ The script will install the python package in the provided directory, and run th

For a more lightweight check, the `--validate-install-only` flag can be used. This will only check that the connector can be installed and returns a spec, no sample config required.

## Contributing

To learn how you can contribute to PyAirbyte, please see our [PyAirbyte Contributors Guide](./CONTRIBUTING.md).

## Changelog

| Version | PR | Description |
Expand Down
8 changes: 7 additions & 1 deletion airbyte/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
"""AirbyteLib brings Airbyte ELT to every Python developer."""
"""PyAirbyte brings Airbyte ELT to every Python developer.

.. include:: ../README.md

"""
from __future__ import annotations

from airbyte._factories.cache_factories import get_default_cache, new_local_cache
Expand All @@ -24,3 +28,5 @@
"SecretSource",
"Source",
]

__docformat__ = "google"
8 changes: 4 additions & 4 deletions airbyte/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ def __repr__(self) -> str:
return f"{class_name}({properties_str})"


# AirbyteLib Internal Errors (these are probably bugs)
# PyAirbyte Internal Errors (these are probably bugs)


@dataclass
Expand All @@ -117,12 +117,12 @@ class AirbyteLibInternalError(AirbyteError):
help_url = NEW_ISSUE_URL


# AirbyteLib Input Errors (replaces ValueError for user input)
# PyAirbyte Input Errors (replaces ValueError for user input)


@dataclass
class AirbyteLibInputError(AirbyteError, ValueError):
"""The input provided to AirbyteLib did not match expected validation rules.
"""The input provided to PyAirbyte did not match expected validation rules.

This inherits from ValueError so that it can be used as a drop-in replacement for
ValueError in the Airbyte Lib API.
Expand All @@ -146,7 +146,7 @@ class AirbyteLibNoStreamsSelectedError(AirbyteLibInputError):
available_streams: list[str] | None = None


# AirbyteLib Cache Errors
# PyAirbyte Cache Errors


class AirbyteLibCacheError(AirbyteError):
Expand Down
2 changes: 1 addition & 1 deletion airbyte/secrets.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Copyright (c) 2023 Airbyte, Inc., all rights reserved.
"""Secrets management for AirbyteLib."""
"""Secrets management for PyAirbyte."""
from __future__ import annotations

import contextlib
Expand Down
4 changes: 2 additions & 2 deletions airbyte/strategies.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# Copyright (c) 2023 Airbyte, Inc., all rights reserved.

"""Read and write strategies for AirbyteLib."""
"""Read and write strategies for PyAirbyte."""
from __future__ import annotations

from enum import Enum


class WriteStrategy(str, Enum):
"""Read strategies for AirbyteLib."""
"""Read strategies for PyAirbyte."""

MERGE = "merge"
"""Merge new records with existing records.
Expand Down
31 changes: 0 additions & 31 deletions docs.py

This file was deleted.

1 change: 1 addition & 0 deletions docs/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
generated
14 changes: 0 additions & 14 deletions docs/frame.html.jinja2

This file was deleted.

40 changes: 40 additions & 0 deletions docs/generate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Copyright (c) 2023 Airbyte, Inc., all rights reserved.
from __future__ import annotations

import os
import pathlib
import shutil

import pdoc

import airbyte as ab


def run() -> None:
"""Generate docs for all public modules in airbyte_lib and save them to docs/generated.

Public modules are:
* The main airbyte_lib module
* All directory modules in airbyte_lib that don't start with an underscore.
"""
public_modules = ["airbyte"]

# recursively delete the docs/generated folder if it exists
if pathlib.Path("docs/generated").exists():
shutil.rmtree("docs/generated")

# All files and folders in `airbyte_lib` that don't start with "_" are treated as public.
for submodule in os.listdir("airbyte"):
submodule_path = pathlib.Path(f"airbyte/{submodule}")
if not submodule.startswith("_"):
public_modules.append(submodule_path)

pdoc.render.configure(
template_directory="docs",
show_source=False,
search=False,
)
pdoc.pdoc(
*public_modules,
output_directory=pathlib.Path("docs/generated"),
)
Loading
Loading