distman


Namedistman JSON
Version 0.6.1 PyPI version JSON
download
home_pagehttp://github.com/rsgalloway/distman
SummarySimple software distribution for complex pipelines
upload_time2025-07-08 13:59:20
maintainerNone
docs_urlNone
authorRyan Galloway
requires_python>=3.6
licenseBSD 3-Clause License
keywords
VCS
bugtrack_url
requirements envstack gitdb GitPython smmap dataclasses htmlmin jsmin
Travis-CI No Travis.
coveralls test coverage No coveralls.
            distman
=======

Simple software distribution for complex pipelines,

`distman` is a config-driven deployment tool that performs safe, versioned rollouts
of software, scripts, and configuration files to predefined locations on the
filesystem. It’s ideal for environments where deterministic deployments,
environment-aware transforms, and clean rollback are more important than packaging
or pip installation.

When used alongside [envstack](https://github.com/rsgalloway/envstack), distman
can act as a drop-in alternative to virtualenv or Python packaging, enabling you
to:

- Install Python tools and libraries via source-controlled builds
- Swap or rollback versions using atomic symlinks
- Configure and isolate runtime environments using .env files
- Avoid the overhead of pip/venv/pyproject setups for internal tools or scripts

## Installation

The easiest way to install:

```bash
$ pip install -U distman
```

Alternatively, use the provided Makefile to build the requirements and dist to
the deplyoment area:

```bash
$ make install
```

Files, directories and links can be distributed from any folder or git repo
containing a `dist.json` file.

## Quickstart

`distman` looks for a dist file called `dist.json` at the root of a directory or
git repo. The dist file defines the file distrubution instructions.

The basic format of the `dist.json` file is:

```json
{
    "author": "<email>",
    "targets": {
        "<target>": {
            "source": "<source-path>",
            "destination": "<target-path>"
        },
    }
}
```

where `<source-path>` is the relative path to the source file, directory or
link, and `<target-path>` is the target destination path, and `<target>` is a
named target label to use when running `distman` commands. You can define as
many targets as you need.

See the `dist.json` file in this repo for an example.

Target paths can include environment variables, such as those defined in the
`distman.env` envstack file, where variables in paths are defined with curly
brackets only, e.g.:

```bash
"{DEPLOY_ROOT}/lib/python/distman"
```

When files are distributed (or disted), they are copied to a `versions` folder
and a symlink is created to the version. When a new version is disted, the
version number is incremented and the link is updated.

#### Wildcards

You can use shell-style wildcards (e.g., *) in the "source" field of a target
definition to match multiple files or directories. This is useful when you want
to distribute a group of files without listing each one individually.

When using wildcards, you must also use numeric substitution variables (%1, %2,
etc.) in the "destination" path. These correspond to the wildcard matches in
order of appearance.

```json
"targets": {
  "build": {
    "source": "build/*.py",
    "destination": "{DEPLOY_ROOT}/lib/python/%1"
  }
}
```

In this example:

- `build/*.py` expands to all `.py` files in the `build/` folder.
- Each matched file is symlinked to `{DEPLOY_ROOT}/lib/python/filename.py`.

> Wildcards are expanded at runtime using Python's glob and fnmatch mechanisms.
Matching results are processed and symlinked individually.

#### Transforms

`distman` supports a customizable pipeline of transforms that operate on each
target before final distribution. These transforms can run:

- Custom Python functions (func)
- Shell commands (script)

Pipeline steps can be defined globally at the top of a dist.json file, or
per-target:

```json
"pipeline": {
    "formatting": {
        "script": ["black --check {input}"]
    },
    "replace_tokens": {
        "func": "distman.transform.replace_tokens",
        "options": {
            "tokens": { "__VERSION__": "1.2.3" }
        }
    }
}
```

## Usage

To dist files defined in a `dist.json` file (remove -d when ready):

```bash
$ distman -d
```

This will dist files to the `${DEPLOY_ROOT}` folder defined in the provided
`distman.env` [envstack](https://github.com/rsgalloway/envstack) file and might
look something like this when disted:

```
${DEPLOY_ROOT}
├── bin
│   ├── distman -> versions/distman.0.c73fe42
│   └── versions
│       └── distman.0.c73fe42
└── lib
    └── python
        ├── distman -> versions/distman.0.c73fe42
        └── versions
            └── distman.0.c73fe42
                ├── cli.py
                ├── config.py
                ├── dist.py
                ├── __init__.py
                ├── logger.py
                ├── source.py
                └── util.py
```

To override the deployment folder, update the `distman.env` environment stack
file then re-dist:

```bash
$ distman [-d]
```

By default, `distman` dists to a prod folder under `${DEPLOY_ROOT}`. This can be
changed at any time using `${ENV}` or updating or modifying the `distman.env`
envstack file:

```bash
$ ENV=dev distman [-d]
```

This will change `prod` to `dev` in the target deplyment path. This is useful
for deploying files or code to different development environments.

## Dist Info

When disting files, `distman` will create hidden dist info files that meta data
about the source files. For example, if the source file is called `foobar.py`
then the dist info file that will be created will be called `.foobar.py.dist`.
The dist info files will be created at the deployment root.

## Config

Most configuration is done in the `distman.env`
[envstack](https://github.com/rsgalloway/envstack) file.

Default config settings are in the config.py module. The following environment
variables are supported:

| Variable     | Description |
|--------------|-------------|
| $DEPLOY_ROOT | file deployment root directory |
| $ENV         | target environment (e.g. prod or dev) |
| $LOG_DIR     | directory to write log files |
| $LOG_LEVEL   | logging level to use (DEBUG, INFO, etc) |
| $ROOT        | dist root directory |

            

Raw data

            {
    "_id": null,
    "home_page": "http://github.com/rsgalloway/distman",
    "name": "distman",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.6",
    "maintainer_email": null,
    "keywords": null,
    "author": "Ryan Galloway",
    "author_email": "ryan@rsgalloway.com",
    "download_url": "https://files.pythonhosted.org/packages/76/44/2826944514711294ade83e6e1911e0d137b6c5b7d9eb5814a60babd9b915/distman-0.6.1.tar.gz",
    "platform": null,
    "description": "distman\n=======\n\nSimple software distribution for complex pipelines,\n\n`distman` is a config-driven deployment tool that performs safe, versioned rollouts\nof software, scripts, and configuration files to predefined locations on the\nfilesystem. It\u2019s ideal for environments where deterministic deployments,\nenvironment-aware transforms, and clean rollback are more important than packaging\nor pip installation.\n\nWhen used alongside [envstack](https://github.com/rsgalloway/envstack), distman\ncan act as a drop-in alternative to virtualenv or Python packaging, enabling you\nto:\n\n- Install Python tools and libraries via source-controlled builds\n- Swap or rollback versions using atomic symlinks\n- Configure and isolate runtime environments using .env files\n- Avoid the overhead of pip/venv/pyproject setups for internal tools or scripts\n\n## Installation\n\nThe easiest way to install:\n\n```bash\n$ pip install -U distman\n```\n\nAlternatively, use the provided Makefile to build the requirements and dist to\nthe deplyoment area:\n\n```bash\n$ make install\n```\n\nFiles, directories and links can be distributed from any folder or git repo\ncontaining a `dist.json` file.\n\n## Quickstart\n\n`distman` looks for a dist file called `dist.json` at the root of a directory or\ngit repo. The dist file defines the file distrubution instructions.\n\nThe basic format of the `dist.json` file is:\n\n```json\n{\n    \"author\": \"<email>\",\n    \"targets\": {\n        \"<target>\": {\n            \"source\": \"<source-path>\",\n            \"destination\": \"<target-path>\"\n        },\n    }\n}\n```\n\nwhere `<source-path>` is the relative path to the source file, directory or\nlink, and `<target-path>` is the target destination path, and `<target>` is a\nnamed target label to use when running `distman` commands. You can define as\nmany targets as you need.\n\nSee the `dist.json` file in this repo for an example.\n\nTarget paths can include environment variables, such as those defined in the\n`distman.env` envstack file, where variables in paths are defined with curly\nbrackets only, e.g.:\n\n```bash\n\"{DEPLOY_ROOT}/lib/python/distman\"\n```\n\nWhen files are distributed (or disted), they are copied to a `versions` folder\nand a symlink is created to the version. When a new version is disted, the\nversion number is incremented and the link is updated.\n\n#### Wildcards\n\nYou can use shell-style wildcards (e.g., *) in the \"source\" field of a target\ndefinition to match multiple files or directories. This is useful when you want\nto distribute a group of files without listing each one individually.\n\nWhen using wildcards, you must also use numeric substitution variables (%1, %2,\netc.) in the \"destination\" path. These correspond to the wildcard matches in\norder of appearance.\n\n```json\n\"targets\": {\n  \"build\": {\n    \"source\": \"build/*.py\",\n    \"destination\": \"{DEPLOY_ROOT}/lib/python/%1\"\n  }\n}\n```\n\nIn this example:\n\n- `build/*.py` expands to all `.py` files in the `build/` folder.\n- Each matched file is symlinked to `{DEPLOY_ROOT}/lib/python/filename.py`.\n\n> Wildcards are expanded at runtime using Python's glob and fnmatch mechanisms.\nMatching results are processed and symlinked individually.\n\n#### Transforms\n\n`distman` supports a customizable pipeline of transforms that operate on each\ntarget before final distribution. These transforms can run:\n\n- Custom Python functions (func)\n- Shell commands (script)\n\nPipeline steps can be defined globally at the top of a dist.json file, or\nper-target:\n\n```json\n\"pipeline\": {\n    \"formatting\": {\n        \"script\": [\"black --check {input}\"]\n    },\n    \"replace_tokens\": {\n        \"func\": \"distman.transform.replace_tokens\",\n        \"options\": {\n            \"tokens\": { \"__VERSION__\": \"1.2.3\" }\n        }\n    }\n}\n```\n\n## Usage\n\nTo dist files defined in a `dist.json` file (remove -d when ready):\n\n```bash\n$ distman -d\n```\n\nThis will dist files to the `${DEPLOY_ROOT}` folder defined in the provided\n`distman.env` [envstack](https://github.com/rsgalloway/envstack) file and might\nlook something like this when disted:\n\n```\n${DEPLOY_ROOT}\n\u251c\u2500\u2500 bin\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 distman -> versions/distman.0.c73fe42\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 versions\n\u2502\u00a0\u00a0     \u2514\u2500\u2500 distman.0.c73fe42\n\u2514\u2500\u2500 lib\n    \u2514\u2500\u2500 python\n        \u251c\u2500\u2500 distman -> versions/distman.0.c73fe42\n        \u2514\u2500\u2500 versions\n            \u2514\u2500\u2500 distman.0.c73fe42\n             \u00a0\u00a0 \u251c\u2500\u2500 cli.py\n             \u00a0\u00a0 \u251c\u2500\u2500 config.py\n             \u00a0\u00a0 \u251c\u2500\u2500 dist.py\n             \u00a0\u00a0 \u251c\u2500\u2500 __init__.py\n             \u00a0\u00a0 \u251c\u2500\u2500 logger.py\n             \u00a0\u00a0 \u251c\u2500\u2500 source.py\n             \u00a0\u00a0 \u2514\u2500\u2500 util.py\n```\n\nTo override the deployment folder, update the `distman.env` environment stack\nfile then re-dist:\n\n```bash\n$ distman [-d]\n```\n\nBy default, `distman` dists to a prod folder under `${DEPLOY_ROOT}`. This can be\nchanged at any time using `${ENV}` or updating or modifying the `distman.env`\nenvstack file:\n\n```bash\n$ ENV=dev distman [-d]\n```\n\nThis will change `prod` to `dev` in the target deplyment path. This is useful\nfor deploying files or code to different development environments.\n\n## Dist Info\n\nWhen disting files, `distman` will create hidden dist info files that meta data\nabout the source files. For example, if the source file is called `foobar.py`\nthen the dist info file that will be created will be called `.foobar.py.dist`.\nThe dist info files will be created at the deployment root.\n\n## Config\n\nMost configuration is done in the `distman.env`\n[envstack](https://github.com/rsgalloway/envstack) file.\n\nDefault config settings are in the config.py module. The following environment\nvariables are supported:\n\n| Variable     | Description |\n|--------------|-------------|\n| $DEPLOY_ROOT | file deployment root directory |\n| $ENV         | target environment (e.g. prod or dev) |\n| $LOG_DIR     | directory to write log files |\n| $LOG_LEVEL   | logging level to use (DEBUG, INFO, etc) |\n| $ROOT        | dist root directory |\n",
    "bugtrack_url": null,
    "license": "BSD 3-Clause License",
    "summary": "Simple software distribution for complex pipelines",
    "version": "0.6.1",
    "project_urls": {
        "Homepage": "http://github.com/rsgalloway/distman"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "76442826944514711294ade83e6e1911e0d137b6c5b7d9eb5814a60babd9b915",
                "md5": "7e621053f8672aa36ffa4e2e9e688424",
                "sha256": "3a314d6566fea440f96f74cd02b9d111911a37d20fa0d6ce1094f8ba42e9c02d"
            },
            "downloads": -1,
            "filename": "distman-0.6.1.tar.gz",
            "has_sig": false,
            "md5_digest": "7e621053f8672aa36ffa4e2e9e688424",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.6",
            "size": 34613,
            "upload_time": "2025-07-08T13:59:20",
            "upload_time_iso_8601": "2025-07-08T13:59:20.130803Z",
            "url": "https://files.pythonhosted.org/packages/76/44/2826944514711294ade83e6e1911e0d137b6c5b7d9eb5814a60babd9b915/distman-0.6.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-07-08 13:59:20",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "rsgalloway",
    "github_project": "distman",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "requirements": [
        {
            "name": "envstack",
            "specs": [
                [
                    ">=",
                    "0.8.9"
                ]
            ]
        },
        {
            "name": "gitdb",
            "specs": [
                [
                    "==",
                    "4.0.11"
                ]
            ]
        },
        {
            "name": "GitPython",
            "specs": [
                [
                    "==",
                    "3.1.43"
                ]
            ]
        },
        {
            "name": "smmap",
            "specs": [
                [
                    "==",
                    "5.0.1"
                ]
            ]
        },
        {
            "name": "dataclasses",
            "specs": []
        },
        {
            "name": "htmlmin",
            "specs": [
                [
                    "==",
                    "0.1.12"
                ]
            ]
        },
        {
            "name": "jsmin",
            "specs": [
                [
                    "==",
                    "3.0.1"
                ]
            ]
        }
    ],
    "lcname": "distman"
}
        
Elapsed time: 0.54087s