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
10 changes: 8 additions & 2 deletions .github/workflows/push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
- main
tags:
- "*" # Skip the workflow on the main branch without tags
workflow_dispatch:

concurrency: ci-${{ github.ref }} # to avoid tag collisions in the ECR
env:
Expand Down Expand Up @@ -63,8 +64,13 @@ jobs:
- name: Set image tag
id: tag
run: |
TAG="${GITHUB_REF##*/}"
IS_SEMANTIC_TAG=$(echo "$TAG" | grep -q '^v\?[0-9]\+\.[0-9]\+\.[0-9]\+$' && echo true || echo false)
REF="${GITHUB_REF##*/}"
if [ "${{ github.ref_type }}" = "tag" ]; then
TAG="$REF"
else
TAG="$REF-${{ github.run_number }}"
fi
IS_SEMANTIC_TAG=$(echo "$REF" | grep -q '^[0-9]\+\.[0-9]\+\.[0-9]\+$' && echo true || echo false)
echo "is_semantic_tag=$IS_SEMANTIC_TAG" | tee -a $GITHUB_OUTPUT
echo "app_image_tag=$TAG" | tee -a $GITHUB_OUTPUT

Expand Down
48 changes: 48 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@
- [Logging](#logging)
- [Development](#development)
- [Integration](#integration)
- [Addendum](#addendum)
- [Generating a Personal Access Token (PAT) for GitHub](#generating-a-personal-access-token-pat-for-github)
- [Personal repository](#personal-repository)
- [Repository in a GitHub organisation](#repository-in-a-github-organisation)
- [Using private git dependencies](#using-private-git-dependencies)


# Custom Python Component
Expand Down Expand Up @@ -82,6 +87,8 @@ The git configuration object supports the following parameters:
- `pat`: Private repository, Personal Access Token.
- `ssh`: Private repository, SSH key.
- `#token`: Personal Access Token (`"auth": "pat"` only). This value will be encrypted in Keboola Storage.
The same token also authenticates private git dependencies declared in `[tool.uv.sources]` in your `pyproject.toml`,
so there is no need to embed tokens directly in the source file.
- `ssh_keys`: SSH keys configuration object (`"auth": "ssh"` only).


Expand Down Expand Up @@ -582,3 +589,44 @@ docker compose up test
For details on deployment and integration with Keboola, refer to the
[deployment section of the developer
documentation](https://developers.keboola.com/extend/component/deployment/).


## Addendum

### Generating a Personal Access Token (PAT) for GitHub

#### Personal repository

1. Go to **GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens**
2. Click **Generate new token**
3. Under **Repository access**, select your repository
4. Under **Repository permissions**, enable **Contents: Read-only**
5. Click **Generate token** and copy the value

#### Repository in a GitHub organisation

1. Same steps as above, but set **Resource owner** to your organisation
2. Under **Repository permissions**, enable **Contents: Read-only**
3. The organisation owner may need to approve the token before it works — check your organisation's token approval settings
4. If your organisation enforces SAML SSO: after generating the token, open its detail page and click **Configure SSO → Authorize** next to your organisation

### Using private git dependencies

If your repository's `pyproject.toml` references other private repositories as
dependencies via `[tool.uv.sources]`, the component will authenticate against
those using the same PAT — no need to embed tokens in the source file.

This requires a `uv.lock` committed alongside `pyproject.toml`. To generate it
locally when the dependency is in a private repository, make sure your git
credentials for github.com are configured first:

- With the `gh` CLI: `gh auth setup-git`
- Without it, add an entry to `~/.netrc`:
```
machine github.com
login x-token-auth
password YOUR_PAT
```
Then `chmod 600 ~/.netrc`.

Then run `uv lock` and commit the result.
13 changes: 13 additions & 0 deletions src/source_git.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import subprocess
import sys
from pathlib import Path
from urllib.parse import urlparse

from keboola.component.exceptions import UserException

Expand Down Expand Up @@ -43,8 +44,20 @@ def _set_up_token_auth(self) -> None:
self.repo_auth_url = self.git_cfg.url.replace(
"https://", f"https://x-token-auth:{self.git_cfg.encrypted_token}@"
)
self._set_up_netrc(self.git_cfg.url, self.git_cfg.encrypted_token)
logging.info("Git token authentication set up for HTTPS URL.")

@staticmethod
def _set_up_netrc(repo_url: str, token: str) -> None:
parsed = urlparse(repo_url)
if not parsed.hostname:
return
netrc_path = Path.home() / ".netrc"
entry = f"machine {parsed.hostname}\nlogin x-token-auth\npassword {token}\n"
with open(netrc_path, "w") as f:
f.write(entry)
os.chmod(netrc_path, 0o600)

def _set_up_ssh_command(self) -> None:
if not self.git_cfg.ssh_keys.keys.encrypted_private:
if self.git_cfg.auth == AuthEnum.SSH:
Expand Down
2 changes: 1 addition & 1 deletion src/venv_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def prepare_venv(py_version: str, base_path: Path) -> Path:
main_script_file (str): Path to the main script file.
"""
venv_path = base_path / ".venv"
args = ["uv", "venv", "-p", py_version, str(venv_path)]
args = ["uv", "venv", "-p", py_version, "--clear", str(venv_path)]

SubprocessRunner.run(args, "Environment created successfully.", "Environment creation failed.")

Expand Down
Loading
Loading