Metadata-Version: 2.4
Name: pjdev-gitlab
Version: 5.0.0
Project-URL: Documentation, https://gitlab.purplejay.io/keystone/python/-/tree/main/pjdev-gitlab/README.md
Project-URL: Issues, https://gitlab.purplejay.io/keystone/python/-/issues
Project-URL: Source, https://gitlab.purplejay.io/keystone/python
Author-email: Purple Jay LLC <developers@purplejay.io>
License-Expression: MIT
License-File: LICENSE.txt
Classifier: Development Status :: 4 - Beta
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Requires-Python: >=3.12
Requires-Dist: httpx
Requires-Dist: loguru
Requires-Dist: pydantic-settings>=2.13.1
Requires-Dist: pydantic>=2.12.5
Provides-Extra: dev
Requires-Dist: ruff; extra == 'dev'
Provides-Extra: test
Requires-Dist: coverage; extra == 'test'
Requires-Dist: pytest; extra == 'test'
Requires-Dist: pytest-asyncio; extra == 'test'
Requires-Dist: respx; extra == 'test'
Description-Content-Type: text/markdown

# pjdev-gitlab

[![PyPI - Version](https://img.shields.io/pypi/v/pjdev-gitlab.svg)](https://pypi.org/project/pjdev-gitlab)
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/pjdev-gitlab.svg)](https://pypi.org/project/pjdev-gitlab)

Async GitLab automation SDK. Wraps the GitLab REST API v4 directly with `httpx.AsyncClient` and Pydantic models. Covers issues, merge requests, repository files, and the generic package registry.

-----

## Installation

```console
pip install pjdev-gitlab
```

## Configuration

`pjdev-gitlab` reads `GL_*` environment variables (or accepts the same values
via `init()`):

| variable | required | purpose |
| --- | --- | --- |
| `GL_TOKEN` | yes | personal/group/project access token (`api` scope) |
| `GL_GITLAB_URL` | yes | base URL, e.g. `https://gitlab.com` |
| `GL_DEFAULT_PROJECT_ID` | no | default project for service helpers |
| `GL_OUTPUT_PATH` | no | directory for downloaded files |

### Recommended: 1Password + `op run`

On a developer laptop, keep the token in 1Password and inject it into the host
process with [`op run`](https://developer.1password.com/docs/cli/secrets-environment-variables/) —
the secret never sits in your shell environment or on disk in plaintext.

1. Install the 1Password CLI (`brew install --cask 1password-cli`) and turn on
   **Settings → Developer → Integrate with 1Password CLI** in the desktop app.
2. Store the token in 1Password (e.g. an API Credential titled
   `GitLab — purplejay` with a `credential` field).
3. Drop a committable `.env.op` next to your project — references only, no
   real secrets:

   ```bash
   # .env.op
   GL_TOKEN="op://Private/GitLab — purplejay/credential"
   GL_GITLAB_URL="https://gitlab.purplejay.io"
   ```

4. Launch your script — or the entire Claude Code session that will use this
   library — under `op run`:

   ```bash
   op run --env-file=.env.op -- python my_script.py
   op run --env-file=.env.op -- claude
   ```

`op run` resolves the references, exports them to the subprocess, and tears
them down on exit. Inside Python, just call `config_service.init()` with no
arguments and the values flow in from the environment.

In CI, skip 1Password and set `GL_TOKEN`/`GL_GITLAB_URL` from the job's
existing variables (e.g. `CI_JOB_TOKEN` for project-scoped operations).

## Usage

```python
import asyncio
from pjdev_gitlab import config_service, issues_service
from pjdev_gitlab.models import StateEvent

async def main() -> None:
    # Token & URL come from GL_TOKEN / GL_GITLAB_URL (e.g. via `op run`).
    config_service.init(default_project_id="my-group/my-project")

    issue = await issues_service.create_issue(
        project_id="my-group/my-project",
        title="Bug: timeout on /widgets",
        description="The endpoint times out under load.\n\n/label ~bug ~priority::high",
        labels=["bug"],
    )
    await issues_service.comment_on_issue(
        project_id="my-group/my-project",
        issue_iid=issue.iid,
        body="Investigating now.",
    )
    await issues_service.set_issue_state(
        project_id="my-group/my-project",
        issue_iid=issue.iid,
        state_event=StateEvent.close,
    )

asyncio.run(main())
```

Run it: `op run --env-file=.env.op -- python my_script.py`.

## Bundled agent skills

Skill files for AI agents ship under `.agents/skills/` inside the installed package, following the [library-skills.io](https://library-skills.io/create/) convention. Topics: issues, merge requests, repository files, generic packages.

## License

`pjdev-gitlab` is distributed under the terms of the [MIT](https://spdx.org/licenses/MIT.html) license.
