Skip to content
Open
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
5 changes: 1 addition & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@
.ripgrep

**/__pycache__/*
**/_site/*
docs/reference/
**/.quarto/*
docs/objects.json
site/
_tasks.py
report.html
_scratchpad.py
Expand Down
5 changes: 2 additions & 3 deletions docs/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
/.quarto/

**/*.quarto_ipynb
# Zensical build output
/site/
74 changes: 0 additions & 74 deletions docs/_quarto.yml

This file was deleted.

45 changes: 18 additions & 27 deletions docs/index.qmd → docs/index.md
Original file line number Diff line number Diff line change
@@ -1,53 +1,44 @@
# Welcome to Invoke Toolkit documentation

[![PyPI - Package Version](https://img.shields.io/pypi/v/invoke-toolkit)](https://pypi.org/project/invoke-toolkit/)

<img alt="PyPI - Package Version" src="https://img.shields.io/pypi/v/invoke-toolkit">
!!! warning
This software is in early development. Expect API breakages until version `0.1.x` is
released.

::: {.callout-warning}
This software is in early development. Expect API breakages until version `0.1.x` is
released.
:::
!!! tip
`invoke-toolkit` extends [`invoke`](https://docs.pyinvoke.org/en/stable/) classes and functions prepending `ToolkitXXX`
for each extended class.

::: {.callout-tip}
`invoke-toolkit` extends [`invoke`](https://docs.pyinvoke.org/en/stable/) classes and functions prepending `ToolkitXXX`
for each extended class.

For compatiblity, when you do `from invoke_toolkit import task, Context` the names are preserved.
:::
For compatibility, when you do `from invoke_toolkit import task, Context` the names are preserved.

Invoke Toolkit is a set of opinionated extensions to the popular [Python invoke library](https://pyinvoke.org)
that allow to create easy to use automation focuses scripts, with the ability to share them in different ways (packages, repos, etc).

It takes advantage of some recent developments in the Python ecosystem such as [`inline scripting`](https://peps.python.org/pep-0723/),
the [`rich`](https://rich.readthedocs.io/en/stable/introduction.html) and [`uv`](https://github.com/astral-sh/uv) pacakge manager.
the [`rich`](https://rich.readthedocs.io/en/stable/introduction.html) and [`uv`](https://github.com/astral-sh/uv) package manager.


Among its core features it extends the `Context` class with status updates

* <details>
<summary>
Add's some `Context` attributes such as `ctx.status()` or `ctx.print` using [rich](https://rich.readthedocs.io/en/stable/introduction.html)
</summary>
??? example "Context attributes like `ctx.status()` and `ctx.print` using rich"

```{.python}
```python
@task()
def long_task(ctx: Context):
with ctx.status("Doing something slow"):
ctx.run("sleep 1")
```
</details>

* Renames the `inv`/`invoke` to `it`/`invoke-toolkit`, reads the same `tasks.py`.
* Replaces `print()` with `rich`'s Console print (internal logging uses `rich` logger): `it -d`.
* Command echo defaults to `stderr` (`it -e`)
* <details>
<summary>
Populates with built in collections to manage *plugins*
</summary>
```bash
it -xl
```
</details>

??? example "Built in collections to manage *plugins*"

```bash
it -xl
```


## Installation
Expand Down Expand Up @@ -77,7 +68,7 @@ from invoke_toolkit import task, Context

@task()
def build(ctx: Context):
ctx.run("quarto build")
ctx.run("uv run zensical build")
```

## Built in collections
157 changes: 157 additions & 0 deletions docs/packages.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
# Creating Packages

Packages let you share invoke-toolkit tasks as installable Python packages. Once installed, your tasks become automatically available in `intk`.

## Creating a Package

Use the built-in template to scaffold a new package:

```bash
intk -x create.package
```

Or with the full command name:

```bash
invoke-toolkit -x create.package
```

This runs an interactive wizard that prompts you for:

| Prompt | Description | Example |
|--------|-------------|---------|
| `package_name` | The pip-installable name | `invoke-toolkit-aws` |
| `package_slug` | Python import name (auto-derived) | `invoke_toolkit_aws` |
| `extension_short_name` | Short name for the collection | `aws` |
| `collection_name` | How tasks appear in `intk -l` | `aws` |
| `author_name` | Your name | `Jane Doe` |
| `author_email` | Your email | `jane@example.com` |
| `project_description` | Brief description | `AWS automation tasks` |
| `python_version` | Minimum Python version | `3.10` |

## Understanding the Generated Files

After running the command, you'll have a complete package structure:

```
my-package/
├── .copier-answers.yml # Template answers (enables updates)
├── .gitignore
├── pyproject.toml # Package metadata and entry point
├── README.md
└── src/
└── my_package/
├── __init__.py # Collection definition
└── tasks.py # Your tasks
```

### Key Files

**`pyproject.toml`** - Defines your package metadata and the entry point that makes tasks discoverable:

```toml
[project.entry-points."invoke_toolkit.collection"]
"aws" = "invoke_toolkit_aws:collection"
```

**`src/{package_slug}/__init__.py`** - Creates a collection that auto-discovers tasks:

```python
collection = ToolkitCollection("aws")
collection.add_flat_tasks_from_namespace("invoke_toolkit_aws")
```

**`src/{package_slug}/tasks.py`** - Where you define your tasks using the `@task` decorator.

### The `.copier-answers.yml` File

This file stores your answers from the template wizard:

```yaml
_src_path: gh:your-org/invoke-toolkit
package_name: invoke-toolkit-aws
package_slug: invoke_toolkit_aws
# ... other answers
```

!!! warning
Do not delete `.copier-answers.yml` - it enables updating your package when the template changes.

## Updating a Package from Template Changes

When the invoke-toolkit template is updated with improvements or fixes, you can pull those changes into your package.

### Running an Update

From your package directory:

```bash
copier update
```

This will:

1. Detect the template version your package was created from
2. Download the latest template
3. Re-apply your answers to generate updated files
4. Merge changes with your local modifications

### What Happens During an Update

Copier performs a three-way merge:

- **Template changes** are applied to files generated from `.jinja` templates
- **Your local changes** to those files are preserved when possible
- **Conflicts** are marked for manual resolution (like git conflicts)

### Protected Files

Some files are excluded from updates via `_preserve_paths` in the template:

```yaml
_preserve_paths:
- .gitignore
```

These files are only created once and never overwritten, even if the template changes.

### Best Practices

1. **Commit before updating** - Always have a clean git state before running `copier update`
2. **Review the diff** - After updating, review changes with `git diff`
3. **Test your tasks** - Run `intk -l` to verify tasks still load correctly
4. **Resolve conflicts** - Look for conflict markers (`<<<<<<<`) and resolve manually

## Troubleshooting

### Tasks not appearing in `intk -l`

- Verify the package is installed: `pip list | grep your-package`
- Check the entry point in `pyproject.toml` matches your collection name
- Ensure `__init__.py` exports the `collection` object

### `copier update` fails

- Ensure `.copier-answers.yml` exists in your package root
- Check you have network access to the template repository
- Try `copier update --trust` if prompted about unsafe operations

### Import errors after update

- The template may have changed the package structure
- Check `__init__.py` imports match your actual module layout
- Run `pip install -e .` to reinstall in development mode

### Conflicts during update

When you see conflict markers:

```
<<<<<<< HEAD
your local changes
=======
template changes
>>>>>>> template
```

Edit the file to keep the correct version, remove the markers, and commit.
2 changes: 1 addition & 1 deletion docs/programs.qmd → docs/programs.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Programs {#sec-prg}
# Programs

Using `invoke_toolkit.program.ToolkitProgram` for your script allows you to
modify more settings than what the CLI normally provides. Programs live inside Python packages so you will have a top level `pyproject.toml`.
Expand Down
6 changes: 6 additions & 0 deletions docs/reference/collections.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Collections

::: invoke_toolkit.collections
options:
show_root_heading: true
show_source: true
6 changes: 6 additions & 0 deletions docs/reference/config.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Config

::: invoke_toolkit.config
options:
show_root_heading: true
show_source: true
6 changes: 6 additions & 0 deletions docs/reference/context.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Context

::: invoke_toolkit.context
options:
show_root_heading: true
show_source: true
6 changes: 6 additions & 0 deletions docs/reference/executor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Executor

::: invoke_toolkit.executor
options:
show_root_heading: true
show_source: true
6 changes: 6 additions & 0 deletions docs/reference/extensions/config.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Config

::: invoke_toolkit.extensions.tasks.config
options:
show_root_heading: true
show_source: true
6 changes: 6 additions & 0 deletions docs/reference/extensions/create.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Create

::: invoke_toolkit.extensions.tasks.create
options:
show_root_heading: true
show_source: true
6 changes: 6 additions & 0 deletions docs/reference/extensions/dist.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Dist

::: invoke_toolkit.extensions.tasks.dist
options:
show_root_heading: true
show_source: true
6 changes: 6 additions & 0 deletions docs/reference/extensions/shell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Shell

::: invoke_toolkit.extensions.tasks.shell
options:
show_root_heading: true
show_source: true
Loading
Loading