urun-cli 0.1.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. urun_cli-0.1.1/.dagger-pipeline.yaml +5 -0
  2. urun_cli-0.1.1/.env.example +11 -0
  3. urun_cli-0.1.1/.envrc +44 -0
  4. urun_cli-0.1.1/.github/CODEOWNERS +3 -0
  5. urun_cli-0.1.1/.github/actionlint.yaml +4 -0
  6. urun_cli-0.1.1/.github/dependabot.yml +10 -0
  7. urun_cli-0.1.1/.github/workflows/ci.yml +87 -0
  8. urun_cli-0.1.1/.github/workflows/precommit.yaml +80 -0
  9. urun_cli-0.1.1/.github/workflows/publish.yaml +31 -0
  10. urun_cli-0.1.1/.github/workflows/release.yaml +46 -0
  11. urun_cli-0.1.1/.gitignore +14 -0
  12. urun_cli-0.1.1/.markdownlint-cli2.yaml +15 -0
  13. urun_cli-0.1.1/.pre-commit-config.yaml +64 -0
  14. urun_cli-0.1.1/CHANGELOG.md +7 -0
  15. urun_cli-0.1.1/CONTRIBUTING.md +51 -0
  16. urun_cli-0.1.1/LICENSE +21 -0
  17. urun_cli-0.1.1/PKG-INFO +130 -0
  18. urun_cli-0.1.1/README.md +108 -0
  19. urun_cli-0.1.1/SECURITY.md +21 -0
  20. urun_cli-0.1.1/SPEC.md +467 -0
  21. urun_cli-0.1.1/SPEC_EXTERNAL.md +773 -0
  22. urun_cli-0.1.1/SPEC_TRACKING.md +88 -0
  23. urun_cli-0.1.1/compose.minio.yml +21 -0
  24. urun_cli-0.1.1/flake.lock +82 -0
  25. urun_cli-0.1.1/flake.nix +33 -0
  26. urun_cli-0.1.1/pyproject.toml +115 -0
  27. urun_cli-0.1.1/src/urun/__init__.py +1 -0
  28. urun_cli-0.1.1/src/urun/api.py +189 -0
  29. urun_cli-0.1.1/src/urun/cli.py +148 -0
  30. urun_cli-0.1.1/src/urun/config.py +115 -0
  31. urun_cli-0.1.1/src/urun/deps.py +92 -0
  32. urun_cli-0.1.1/src/urun/discovery.py +204 -0
  33. urun_cli-0.1.1/src/urun/errors.py +10 -0
  34. urun_cli-0.1.1/src/urun/manifest.py +78 -0
  35. urun_cli-0.1.1/tests/test_api.py +17 -0
  36. urun_cli-0.1.1/tests/test_api_coverage.py +188 -0
  37. urun_cli-0.1.1/tests/test_api_errors.py +96 -0
  38. urun_cli-0.1.1/tests/test_cli_coverage.py +136 -0
  39. urun_cli-0.1.1/tests/test_config_coverage.py +55 -0
  40. urun_cli-0.1.1/tests/test_config_deps.py +34 -0
  41. urun_cli-0.1.1/tests/test_deps_coverage.py +50 -0
  42. urun_cli-0.1.1/tests/test_discovery.py +37 -0
  43. urun_cli-0.1.1/tests/test_discovery_coverage.py +175 -0
  44. urun_cli-0.1.1/tests/test_http_flow.py +209 -0
  45. urun_cli-0.1.1/tests/test_manifest.py +20 -0
  46. urun_cli-0.1.1/tests/test_minio_integration.py +247 -0
  47. urun_cli-0.1.1/tests/test_path_policy.py +58 -0
  48. urun_cli-0.1.1/tests/test_prod_hardening.py +214 -0
  49. urun_cli-0.1.1/uv.lock +1085 -0
@@ -0,0 +1,5 @@
1
+ global:
2
+ registry_password_env: "REGISTRY_PASSWORD"
3
+
4
+ precommit:
5
+ base_image: "ghcr.io/urun-sh/dagger-rust-ci:1@sha256:a3740705141cd26172cf786311e9bc02b1ca7b535931ef188b779512f4f85bf1"
@@ -0,0 +1,11 @@
1
+ # urun CLI credentials
2
+ URUN_API_URL=https://api.urun.sh/v1
3
+ URUN_API_KEY=urun_00000000000000000000000000000000
4
+ URUN_ORG_ID=org_example
5
+
6
+ # Optional local MinIO integration tests
7
+ URUN_TEST_MINIO_ENDPOINT=127.0.0.1:9000
8
+ URUN_TEST_MINIO_ACCESS_KEY=minioadmin
9
+ URUN_TEST_MINIO_SECRET_KEY=minioadmin
10
+ URUN_TEST_MINIO_BUCKET=urun-cli-test
11
+ URUN_TEST_MINIO_SECURE=0
urun_cli-0.1.1/.envrc ADDED
@@ -0,0 +1,44 @@
1
+ watch_file flake.nix
2
+ watch_file pyproject.toml
3
+ watch_file uv.lock
4
+ watch_file .pre-commit-config.yaml
5
+
6
+ use flake
7
+
8
+ unset PYTHONPATH
9
+
10
+ if has uv; then
11
+ export UV_PYTHON="python3.12"
12
+ _marker=".direnv/uv-synced"
13
+ _need_sync=false
14
+ if [[ ! -d .venv ]] || [[ ! -x .venv/bin/python ]] || [[ ! -f "$_marker" ]] \
15
+ || [[ pyproject.toml -nt "$_marker" ]] \
16
+ || { [[ -f uv.lock ]] && [[ uv.lock -nt "$_marker" ]]; }; then
17
+ _need_sync=true
18
+ elif ! .venv/bin/python --version >/dev/null 2>&1; then
19
+ log_status "venv Python is broken (interpreter not executable), recreating..."
20
+ rm -rf .venv
21
+ _need_sync=true
22
+ fi
23
+ if $_need_sync; then
24
+ uv sync --locked && {
25
+ mkdir -p .direnv
26
+ touch "$_marker"
27
+ }
28
+ fi
29
+
30
+ VIRTUAL_ENV="$PWD/.venv"
31
+ PATH_add "$VIRTUAL_ENV/bin"
32
+ export VIRTUAL_ENV
33
+ fi
34
+
35
+ if has pre-commit && git rev-parse --git-dir > /dev/null 2>&1; then
36
+ _pc_marker=".direnv/pre-commit-installed"
37
+ if [[ ! -f "$_pc_marker" ]] \
38
+ || { [[ -f .pre-commit-config.yaml ]] && [[ .pre-commit-config.yaml -nt "$_pc_marker" ]]; }; then
39
+ pre-commit install --allow-missing-config \
40
+ && pre-commit install --hook-type pre-push --allow-missing-config \
41
+ && mkdir -p .direnv \
42
+ && touch "$_pc_marker"
43
+ fi
44
+ fi
@@ -0,0 +1,3 @@
1
+ # Require Keegan's review for contributed changes. Branch protection lets admins
2
+ # bypass this for maintainer-authored emergency/solo-maintainer merges.
3
+ * @keeganmccallum
@@ -0,0 +1,4 @@
1
+ self-hosted-runner:
2
+ labels:
3
+ - blacksmith-4vcpu-ubuntu-2404
4
+ - blacksmith-4vcpu-ubuntu-2404-arm
@@ -0,0 +1,10 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "github-actions"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "weekly"
7
+ - package-ecosystem: "uv"
8
+ directory: "/"
9
+ schedule:
10
+ interval: "weekly"
@@ -0,0 +1,87 @@
1
+ name: ci
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+
7
+ concurrency:
8
+ group: ${{ github.workflow }}-${{ github.ref }}
9
+ cancel-in-progress: ${{ github.event_name == 'pull_request' }}
10
+
11
+ permissions:
12
+ contents: read
13
+
14
+ jobs:
15
+ test:
16
+ runs-on: ubuntu-24.04
17
+ timeout-minutes: 10
18
+ steps:
19
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
20
+ with:
21
+ persist-credentials: false
22
+ - name: Install uv
23
+ uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
24
+ with:
25
+ enable-cache: true
26
+ - name: Set up Python
27
+ run: uv python install 3.12
28
+ - name: Install dependencies
29
+ run: uv sync --locked
30
+ - name: Run tests with coverage
31
+ run: |
32
+ uv run pytest -q -m 'not minio' \
33
+ --cov=urun \
34
+ --cov-report=term-missing \
35
+ --cov-report=xml
36
+ - name: Add coverage summary
37
+ run: |
38
+ {
39
+ echo '## Coverage'
40
+ echo '```text'
41
+ uv run coverage report
42
+ echo '```'
43
+ } >> "$GITHUB_STEP_SUMMARY"
44
+ - name: Upload coverage XML
45
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
46
+ with:
47
+ name: coverage-xml
48
+ path: coverage.xml
49
+ - name: Build package
50
+ run: uv build
51
+
52
+ minio:
53
+ runs-on: ubuntu-24.04
54
+ timeout-minutes: 10
55
+ steps:
56
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
57
+ with:
58
+ persist-credentials: false
59
+ - name: Install uv
60
+ uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
61
+ with:
62
+ enable-cache: true
63
+ - name: Set up Python
64
+ run: uv python install 3.12
65
+ - name: Install dependencies
66
+ run: uv sync --locked
67
+ - name: Start MinIO
68
+ run: |
69
+ docker run -d --name urun-cli-minio \
70
+ -p 127.0.0.1:9000:9000 \
71
+ -e MINIO_ROOT_USER=minioadmin \
72
+ -e MINIO_ROOT_PASSWORD=minioadmin \
73
+ minio/minio:RELEASE.2025-09-07T16-13-09Z@sha256:14cea493d9a34af32f524e538b8346cf79f3321eff8e708c1e2960462bd8936e server /data --address :9000
74
+ for _ in $(seq 1 60); do
75
+ if curl -fsS http://127.0.0.1:9000/minio/health/live; then
76
+ exit 0
77
+ fi
78
+ sleep 1
79
+ done
80
+ docker logs urun-cli-minio
81
+ exit 1
82
+ - name: Run MinIO integration tests
83
+ env:
84
+ URUN_TEST_MINIO_ENDPOINT: 127.0.0.1:9000
85
+ URUN_TEST_MINIO_ACCESS_KEY: minioadmin
86
+ URUN_TEST_MINIO_SECRET_KEY: minioadmin
87
+ run: uv run pytest -q -m minio
@@ -0,0 +1,80 @@
1
+ name: Pre-commit
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ push:
6
+ branches: [main]
7
+ pull_request:
8
+ branches: [main]
9
+
10
+ concurrency:
11
+ group: ${{ github.workflow }}-${{ github.ref }}
12
+ cancel-in-progress: ${{ github.event_name == 'pull_request' }}
13
+
14
+ permissions:
15
+ contents: read
16
+ packages: read
17
+
18
+ jobs:
19
+ precommit:
20
+ name: Pre-commit Hooks
21
+ # Central Dagger pipeline uses private org credentials; normal CI still runs on fork PRs.
22
+ if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
23
+ runs-on: blacksmith-4vcpu-ubuntu-2404
24
+ steps:
25
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
26
+ with:
27
+ persist-credentials: false
28
+
29
+ - uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
30
+ id: app-token
31
+ with:
32
+ app-id: ${{ secrets.PIPELINE_CI_APP_ID }}
33
+ private-key: ${{ secrets.PIPELINE_CI_APP_PRIVATE_KEY }}
34
+ owner: urun-sh
35
+
36
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
37
+ with:
38
+ repository: urun-sh/dagger-pipeline
39
+ ref: main
40
+ fetch-depth: 0
41
+ token: ${{ steps.app-token.outputs.token }}
42
+ path: .dagger-pipeline
43
+ persist-credentials: false
44
+
45
+ - name: Check out pinned dagger-pipeline commit
46
+ run: |
47
+ git -C .dagger-pipeline checkout --detach d550f10b2c5a09106f65240ca369bc9b0533e74e
48
+ test "$(git -C .dagger-pipeline rev-parse HEAD)" = "d550f10b2c5a09106f65240ca369bc9b0533e74e"
49
+
50
+ - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
51
+ with:
52
+ python-version: "3.12"
53
+
54
+ - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
55
+
56
+ - uses: dagger/dagger-for-github@27b130bf0f79a7f6fbbbe0fbca6760dc9bb40a77 # v8.4.1
57
+ with:
58
+ verb: ""
59
+ args: ""
60
+ version: "0.19.11"
61
+
62
+ - name: Login to GHCR
63
+ run: |
64
+ TOKEN="${{ secrets.GITHUB_TOKEN }}"
65
+ echo "::add-mask::$TOKEN"
66
+ echo "$TOKEN" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
67
+
68
+ - name: Install dagger-pipeline dependencies
69
+ run: uv sync --frozen --project .dagger-pipeline
70
+
71
+ - name: Run pre-commit hooks
72
+ run: |
73
+ dagger run --progress=plain uv run --project .dagger-pipeline --frozen --no-sync python -m recipes.precommit \
74
+ --all-files \
75
+ --show-diff-on-failure \
76
+ --registry-username ${{ github.actor }} \
77
+ ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' && '--skip no-commit-to-branch' || '' }}
78
+ env:
79
+ DAGGER_CLOUD_TOKEN: ${{ secrets.DAGGER_CLOUD_TOKEN }}
80
+ REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
@@ -0,0 +1,31 @@
1
+ name: publish
2
+
3
+ on:
4
+ workflow_dispatch:
5
+
6
+ permissions:
7
+ contents: read
8
+
9
+ jobs:
10
+ build:
11
+ runs-on: ubuntu-24.04
12
+ timeout-minutes: 10
13
+ steps:
14
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
15
+ with:
16
+ persist-credentials: false
17
+ - name: Install uv
18
+ uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
19
+ with:
20
+ enable-cache: true
21
+ - name: Set up Python
22
+ run: uv python install 3.12
23
+ - name: Build package
24
+ run: uv build
25
+ - name: Check package metadata
26
+ run: uvx twine check dist/*
27
+ - name: Upload distributions
28
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
29
+ with:
30
+ name: dist
31
+ path: dist/*
@@ -0,0 +1,46 @@
1
+ name: release
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ workflow_dispatch:
7
+
8
+ concurrency:
9
+ group: ${{ github.workflow }}-${{ github.ref }}
10
+ cancel-in-progress: false
11
+
12
+ permissions:
13
+ contents: write
14
+ id-token: write
15
+
16
+ jobs:
17
+ patch-release:
18
+ # Branch protection is the quality gate; this workflow releases the exact protected main tip.
19
+ if: ${{ !contains(github.event.head_commit.message, '[skip ci]') }}
20
+ runs-on: ubuntu-24.04
21
+ timeout-minutes: 15
22
+ environment: pypi
23
+ steps:
24
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
25
+ with:
26
+ fetch-depth: 0
27
+ persist-credentials: false
28
+ - name: Install uv
29
+ uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
30
+ with:
31
+ enable-cache: false
32
+ - name: Set up Python
33
+ run: uv python install 3.12
34
+ - name: Install dependencies
35
+ run: uv sync --locked
36
+ - name: Create patch release and GitHub release
37
+ env:
38
+ GH_TOKEN: ${{ github.token }}
39
+ run: |
40
+ uv run semantic-release version \
41
+ --patch \
42
+ --no-commit \
43
+ --push \
44
+ --vcs-release
45
+ - name: Publish to PyPI
46
+ uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0
@@ -0,0 +1,14 @@
1
+ .venv/
2
+ .direnv/
3
+ .env
4
+ .env.*
5
+ !.env.example
6
+ __pycache__/
7
+ .pytest_cache/
8
+ .coverage
9
+ coverage.xml
10
+ htmlcov/
11
+ *.py[cod]
12
+ dist/
13
+ build/
14
+ *.egg-info/
@@ -0,0 +1,15 @@
1
+ config:
2
+ # Specs and security docs intentionally include long protocol examples.
3
+ MD013: false
4
+ MD024:
5
+ siblings_only: true
6
+ # Initial specs are imported design docs; avoid churn unrelated to CI intent.
7
+ MD031: false
8
+ MD032: false
9
+ MD040: false
10
+ MD047: false
11
+
12
+ ignores:
13
+ - ".venv/**"
14
+ - "dist/**"
15
+ - "build/**"
@@ -0,0 +1,64 @@
1
+ exclude: '^(\.venv|\.direnv|\.mypy_cache|\.ruff_cache|\.pytest_cache|dist|build|\.dagger-pipeline)/'
2
+
3
+ repos:
4
+ - repo: https://github.com/pre-commit/pre-commit-hooks
5
+ rev: v6.0.0
6
+ hooks:
7
+ - id: check-merge-conflict
8
+ stages: [pre-commit]
9
+ - id: no-commit-to-branch
10
+ args: ["--branch", "main"]
11
+ stages: [pre-commit]
12
+ - id: check-toml
13
+ stages: [pre-commit]
14
+ - id: check-yaml
15
+ args: [--allow-multiple-documents]
16
+ stages: [pre-commit]
17
+ - id: detect-private-key
18
+ stages: [pre-commit]
19
+ - id: end-of-file-fixer
20
+ stages: [pre-commit]
21
+ - id: trailing-whitespace
22
+ stages: [pre-commit]
23
+ - id: mixed-line-ending
24
+ args: [--fix=lf]
25
+ stages: [pre-commit]
26
+
27
+ - repo: https://github.com/DavidAnson/markdownlint-cli2
28
+ rev: v0.21.0
29
+ hooks:
30
+ - id: markdownlint-cli2
31
+ stages: [pre-commit]
32
+
33
+ - repo: https://github.com/rhysd/actionlint
34
+ rev: v1.7.11
35
+ hooks:
36
+ - id: actionlint-system
37
+ stages: [pre-commit]
38
+
39
+ - repo: local
40
+ hooks:
41
+ - id: ruff
42
+ name: ruff
43
+ entry: uv run ruff check --fix
44
+ language: system
45
+ types: [python]
46
+ stages: [pre-commit]
47
+ - id: ruff-format
48
+ name: ruff-format
49
+ entry: uv run ruff format
50
+ language: system
51
+ types: [python]
52
+ stages: [pre-commit]
53
+ - id: pytest
54
+ name: pytest
55
+ entry: uv run pytest -q -m "not minio"
56
+ language: system
57
+ pass_filenames: false
58
+ stages: [pre-push]
59
+ - id: build
60
+ name: build
61
+ entry: uv build
62
+ language: system
63
+ pass_filenames: false
64
+ stages: [manual]
@@ -0,0 +1,7 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0 - Unreleased
4
+
5
+ - Initial end-user `urun deploy` CLI.
6
+ - Manifest generation, file discovery, dependency declaration upload, and API deploy flow.
7
+ - Local fake Edge API and MinIO integration tests.
@@ -0,0 +1,51 @@
1
+ # Contributing
2
+
3
+ ## Setup
4
+
5
+ ```bash
6
+ # Optional but recommended if you use Nix/direnv:
7
+ direnv allow
8
+
9
+ uv sync
10
+ uv run urun --version
11
+ ```
12
+
13
+ ## Checks
14
+
15
+ ```bash
16
+ uv run ruff check .
17
+ uv run ruff format --check .
18
+ uv run pytest -q
19
+ uv run pytest -q -m "not minio" --cov=urun --cov-report=term-missing --cov-report=xml
20
+ uv build
21
+ ```
22
+
23
+ The coverage command prints a missing-line report and writes `coverage.xml` for CI/artifact upload.
24
+
25
+ ## Testing strategy
26
+
27
+ Follow a practical test pyramid:
28
+
29
+ - Prefer fast unit tests for parsing, path policy, manifest/dependency logic, and CLI validation.
30
+ - Use fake HTTP integration tests for the urun API contract and retry/error flows.
31
+ - Keep real-service tests small and explicit; MinIO is the local smoke for presigned upload behavior.
32
+ - Maintain more than three meaningful tests in each active layer: unit, fake-API integration, and real-service MinIO integration.
33
+ - Do not raise coverage by adding broad E2E tests or assertions against incidental implementation details.
34
+
35
+ To run the optional MinIO integration test locally:
36
+
37
+ ```bash
38
+ docker compose -f compose.minio.yml up -d
39
+ URUN_TEST_MINIO_ENDPOINT=127.0.0.1:9000 \
40
+ URUN_TEST_MINIO_ACCESS_KEY=minioadmin \
41
+ URUN_TEST_MINIO_SECRET_KEY=minioadmin \
42
+ uv run pytest -q -m minio
43
+ ```
44
+
45
+ ## Pre-commit
46
+
47
+ This repo follows urun's centralized Dagger pre-commit pipeline in CI. Local hooks live in `.pre-commit-config.yaml`; CI invokes them through `urun-sh/dagger-pipeline`. The Nix/direnv shell provides Dagger and actionlint so maintainers can reproduce the same pre-commit environment locally.
48
+
49
+ ## Scope
50
+
51
+ This repository owns the Python CLI package. Supabase Edge Functions, S3/SQS wiring, builder pods, ZeroFS materialization, and ArgoCD integration are platform components tracked separately.
urun_cli-0.1.1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 urun
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,130 @@
1
+ Metadata-Version: 2.4
2
+ Name: urun-cli
3
+ Version: 0.1.1
4
+ Summary: End-user CLI for deploying apps to urun
5
+ Project-URL: Homepage, https://urun.sh
6
+ Project-URL: Repository, https://github.com/urun-sh/urun-cli
7
+ Project-URL: Issues, https://github.com/urun-sh/urun-cli/issues
8
+ Author: urun
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: cli,deploy,urun
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Software Development :: Build Tools
20
+ Requires-Python: >=3.11
21
+ Description-Content-Type: text/markdown
22
+
23
+ # urun CLI
24
+
25
+ End-user command line client for deploying Python apps to urun.
26
+
27
+ ## Install
28
+
29
+ ```bash
30
+ uv tool install urun-cli
31
+ # or
32
+ pip install urun-cli
33
+ ```
34
+
35
+ The installed executable is still `urun`:
36
+
37
+ ```bash
38
+ urun --version
39
+ ```
40
+
41
+ PyPI does not allow the distribution name `urun`, so ephemeral uv runs need the
42
+ package name explicitly:
43
+
44
+ ```bash
45
+ uvx --from urun-cli urun --version
46
+ # or use the package-matching alias
47
+ uvx urun-cli --version
48
+ ```
49
+
50
+ ## Deploy
51
+
52
+ ```bash
53
+ export URUN_API_KEY=urun_<32hex>
54
+ export URUN_ORG_ID=org_... # bootstrap-era requirement for v1 manifests
55
+ urun deploy app.py
56
+ ```
57
+
58
+ ## Development with uv / Nix
59
+
60
+ This repo includes `flake.nix` and `.envrc` for a reproducible dev shell with uv,
61
+ Python 3.12, Dagger, actionlint, and pre-commit.
62
+
63
+ ```bash
64
+ direnv allow # optional, if you use direnv/nix
65
+ uv sync
66
+ uv run pytest
67
+ uv run urun --version
68
+ uv build
69
+ ```
70
+
71
+ CI uses the same centralized Dagger pre-commit pipeline pattern as `urun`:
72
+ `precommit.yaml` checks out `urun-sh/dagger-pipeline` and runs `recipes.precommit`.
73
+ Normal `ci` remains self-contained and runs on public/fork PRs.
74
+
75
+ Optional local MinIO integration test:
76
+
77
+ ```bash
78
+ docker compose -f compose.minio.yml up -d
79
+ URUN_TEST_MINIO_ENDPOINT=127.0.0.1:9000 \
80
+ URUN_TEST_MINIO_ACCESS_KEY=minioadmin \
81
+ URUN_TEST_MINIO_SECRET_KEY=minioadmin \
82
+ uv run pytest -q -m minio
83
+ ```
84
+
85
+ See `SPEC_TRACKING.md` for spec coverage and remaining gaps.
86
+
87
+ ## Configuration
88
+
89
+ Configuration is read from `urun.toml` when present. CLI flags override config values.
90
+
91
+ ```toml
92
+ [app]
93
+ name = "my-app"
94
+ entrypoint = "src/myapp/main.py"
95
+ python_version = "3.12"
96
+
97
+ [[mounts]]
98
+ local_path = "./assets"
99
+ remote_path = "/app/assets"
100
+
101
+ [deps]
102
+ requirements = "requirements.txt"
103
+ ```
104
+
105
+ Common options:
106
+
107
+ | Option | Description |
108
+ | --- | --- |
109
+ | `-m, --module` | Deploy a Python module entrypoint, e.g. `myapp.main`. |
110
+ | `--name` | Override the derived app name. |
111
+ | `--config` | Use a specific `urun.toml`; relative paths resolve from its directory. |
112
+ | `--api-url` | Override the API URL. |
113
+ | `--api-key` | API key; prefer `URUN_API_KEY` for shell history safety. |
114
+ | `--org-id` | Bootstrap-era org ID required in v1 manifests. |
115
+ | `--no-wait` | Finalize but do not poll for readiness. |
116
+ | `--poll-interval`, `--timeout` | Control readiness polling. |
117
+
118
+ ## Troubleshooting
119
+
120
+ | Error | Fix |
121
+ | --- | --- |
122
+ | `missing API key` | Set `URUN_API_KEY` or pass `--api-key`. |
123
+ | `invalid API key format` | Use `urun_<32 lowercase hex chars>`. |
124
+ | `missing org id` | Set `URUN_ORG_ID` while v1 bootstrap is manual. |
125
+ | `entrypoint not found` | Run from the project root or pass `--config`. |
126
+ | `path is outside the project root` | Move the file under the project or adjust `urun.toml`. |
127
+
128
+ ## License
129
+
130
+ MIT. Local MinIO is used only as an optional S3-compatible test service.