locci 0.1.0__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.
- locci-0.1.0/.gitignore +34 -0
- locci-0.1.0/LICENSE +21 -0
- locci-0.1.0/PKG-INFO +74 -0
- locci-0.1.0/README.md +51 -0
- locci-0.1.0/pyproject.toml +39 -0
- locci-0.1.0/scripts/stress_test.py +52 -0
- locci-0.1.0/src/locci/__init__.py +0 -0
- locci-0.1.0/src/locci/analyzer.py +633 -0
- locci-0.1.0/src/locci/cache.py +321 -0
- locci-0.1.0/src/locci/cli.py +743 -0
- locci-0.1.0/src/locci/diagnostics.py +68 -0
- locci-0.1.0/src/locci/doctor.py +153 -0
- locci-0.1.0/src/locci/exporter.py +161 -0
- locci-0.1.0/src/locci/expressions.py +232 -0
- locci-0.1.0/src/locci/gh_parser.py +592 -0
- locci-0.1.0/src/locci/graph.py +89 -0
- locci-0.1.0/src/locci/hooks.py +85 -0
- locci-0.1.0/src/locci/orchestrator.py +403 -0
- locci-0.1.0/src/locci/parser.py +158 -0
- locci-0.1.0/src/locci/remote_cache.py +109 -0
- locci-0.1.0/src/locci/safety.py +48 -0
- locci-0.1.0/src/locci/sandbox.py +145 -0
- locci-0.1.0/src/locci/secrets.py +49 -0
- locci-0.1.0/src/locci/setup.py +73 -0
- locci-0.1.0/tests/test_analyzer_monorepo.py +56 -0
- locci-0.1.0/tests/test_cache.py +71 -0
- locci-0.1.0/tests/test_cache_globs.py +38 -0
- locci-0.1.0/tests/test_continue_on_error.py +84 -0
- locci-0.1.0/tests/test_detectors.py +104 -0
- locci-0.1.0/tests/test_exporter.py +51 -0
- locci-0.1.0/tests/test_expressions.py +46 -0
- locci-0.1.0/tests/test_expressions_outputs.py +57 -0
- locci-0.1.0/tests/test_gh_parser.py +91 -0
- locci-0.1.0/tests/test_github.py +37 -0
- locci-0.1.0/tests/test_graph_affected.py +59 -0
- locci-0.1.0/tests/test_integration.py +86 -0
- locci-0.1.0/tests/test_orchestrator.py +28 -0
- locci-0.1.0/tests/test_parser.py +45 -0
- locci-0.1.0/tests/test_remote_cache.py +122 -0
- locci-0.1.0/tests/test_sandbox.py +6 -0
- locci-0.1.0/tests/test_secret_export_leak.py +55 -0
- locci-0.1.0/tests/test_secrets.py +43 -0
- locci-0.1.0/tests/test_secrets_broadcast.py +57 -0
- locci-0.1.0/tests/test_services.py +56 -0
- locci-0.1.0/tests/test_upgrade_mvp.py +340 -0
locci-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.pyo
|
|
5
|
+
*.pyd
|
|
6
|
+
.Python
|
|
7
|
+
*.egg
|
|
8
|
+
*.egg-info/
|
|
9
|
+
dist/
|
|
10
|
+
build/
|
|
11
|
+
.eggs/
|
|
12
|
+
.venv/
|
|
13
|
+
venv/
|
|
14
|
+
env/
|
|
15
|
+
.env
|
|
16
|
+
|
|
17
|
+
# Locci cache
|
|
18
|
+
.locci/
|
|
19
|
+
.locci_cache/
|
|
20
|
+
~/.locci/
|
|
21
|
+
|
|
22
|
+
# Editor
|
|
23
|
+
.idea/
|
|
24
|
+
.vscode/
|
|
25
|
+
*.swp
|
|
26
|
+
*.swo
|
|
27
|
+
|
|
28
|
+
# macOS
|
|
29
|
+
.DS_Store
|
|
30
|
+
|
|
31
|
+
# Test artifacts
|
|
32
|
+
.pytest_cache/
|
|
33
|
+
.coverage
|
|
34
|
+
htmlcov/
|
locci-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Locci Developers
|
|
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.
|
locci-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: locci
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A fast, local-first CI engine.
|
|
5
|
+
Author: Locci Developers
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Requires-Python: >=3.9
|
|
8
|
+
Requires-Dist: networkx>=3.0
|
|
9
|
+
Requires-Dist: pydantic>=2.0.0
|
|
10
|
+
Requires-Dist: pyyaml>=6.0.1
|
|
11
|
+
Requires-Dist: rich>=13.0.0
|
|
12
|
+
Requires-Dist: tomli>=2.0.1; python_version < '3.11'
|
|
13
|
+
Requires-Dist: typer>=0.9.0
|
|
14
|
+
Requires-Dist: watchdog>=3.0.0
|
|
15
|
+
Provides-Extra: ai
|
|
16
|
+
Requires-Dist: anthropic>=0.20.0; extra == 'ai'
|
|
17
|
+
Provides-Extra: dev
|
|
18
|
+
Requires-Dist: pytest-asyncio; extra == 'dev'
|
|
19
|
+
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
20
|
+
Provides-Extra: s3
|
|
21
|
+
Requires-Dist: boto3>=1.28.0; extra == 's3'
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
|
|
24
|
+
# Locci (Local CI)
|
|
25
|
+
|
|
26
|
+
Locci is a fast, local-first CI preflight tool that runs the safe parts of your CI on your machine before you push. It uses an embedded DAG engine, content-hash caching, GitHub Actions-aware parsing, and clear skip reporting for unsafe or unsupported work.
|
|
27
|
+
|
|
28
|
+
Locci is intentionally host-native for the MVP: it does not claim to replace your hosted CI runner or Docker-isolate production deploys. Instead, it catches the common lint/test/build failures locally and tells you what still needs remote CI.
|
|
29
|
+
|
|
30
|
+
## Security Caveats
|
|
31
|
+
|
|
32
|
+
**⚠️ Local Safety Heuristics are Best-Effort**
|
|
33
|
+
Locci uses a keyword-based heuristic (looking for words like "deploy", "publish", "release") to identify and skip unsafe side-effect jobs. **This is not a security boundary.** A job that modifies production state without using these specific keywords will still execute locally.
|
|
34
|
+
|
|
35
|
+
**⚠️ Remote Cache Supply Chain Risk**
|
|
36
|
+
When using the `--remote-cache s3://...` feature, Locci pulls and restores cache artifacts directly into your workspace. There is currently no cryptographic signature or authenticity verification on these artifacts. Anyone with write access to the shared cache bucket could plant a malicious payload or falsify a test outcome. Use shared remote caching with trusted teams only.
|
|
37
|
+
|
|
38
|
+
## Why Python?
|
|
39
|
+
|
|
40
|
+
Locci is distributed via `pip` and written in Python 3.9+. While traditional tools often aim for a single static binary to avoid runtime dependencies, we deliberately chose Python to make installation ubiquitous across all OSes via PyPI, and to allow for rapid iteration and community-driven plugins.
|
|
41
|
+
|
|
42
|
+
**The Tradeoff**: You will need a Python 3.9+ runtime to use Locci, even if your project is written in Node.js, Go, or Rust.
|
|
43
|
+
|
|
44
|
+
**Recommendation**: We strongly recommend installing Locci globally via `pipx` to isolate its dependencies from your system Python:
|
|
45
|
+
```bash
|
|
46
|
+
pipx install locci
|
|
47
|
+
```
|
|
48
|
+
This gives you a globally available `locci` command that feels exactly like a static binary, without cluttering your environment.
|
|
49
|
+
|
|
50
|
+
## Usage
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# First-time setup in a repo
|
|
54
|
+
locci setup
|
|
55
|
+
|
|
56
|
+
# Daily local CI check
|
|
57
|
+
locci check
|
|
58
|
+
|
|
59
|
+
# Affected pre-push check
|
|
60
|
+
locci preflight
|
|
61
|
+
|
|
62
|
+
# Watch for file changes and incrementally rerun only affected steps
|
|
63
|
+
locci watch
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Useful commands:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
locci setup --preview # print the generated locci.yml without writing
|
|
70
|
+
locci check --dry-run # show the local execution graph
|
|
71
|
+
locci check --strict-coverage
|
|
72
|
+
locci hook install # install a managed pre-push hook
|
|
73
|
+
locci doctor # inspect required local tools
|
|
74
|
+
```
|
locci-0.1.0/README.md
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Locci (Local CI)
|
|
2
|
+
|
|
3
|
+
Locci is a fast, local-first CI preflight tool that runs the safe parts of your CI on your machine before you push. It uses an embedded DAG engine, content-hash caching, GitHub Actions-aware parsing, and clear skip reporting for unsafe or unsupported work.
|
|
4
|
+
|
|
5
|
+
Locci is intentionally host-native for the MVP: it does not claim to replace your hosted CI runner or Docker-isolate production deploys. Instead, it catches the common lint/test/build failures locally and tells you what still needs remote CI.
|
|
6
|
+
|
|
7
|
+
## Security Caveats
|
|
8
|
+
|
|
9
|
+
**⚠️ Local Safety Heuristics are Best-Effort**
|
|
10
|
+
Locci uses a keyword-based heuristic (looking for words like "deploy", "publish", "release") to identify and skip unsafe side-effect jobs. **This is not a security boundary.** A job that modifies production state without using these specific keywords will still execute locally.
|
|
11
|
+
|
|
12
|
+
**⚠️ Remote Cache Supply Chain Risk**
|
|
13
|
+
When using the `--remote-cache s3://...` feature, Locci pulls and restores cache artifacts directly into your workspace. There is currently no cryptographic signature or authenticity verification on these artifacts. Anyone with write access to the shared cache bucket could plant a malicious payload or falsify a test outcome. Use shared remote caching with trusted teams only.
|
|
14
|
+
|
|
15
|
+
## Why Python?
|
|
16
|
+
|
|
17
|
+
Locci is distributed via `pip` and written in Python 3.9+. While traditional tools often aim for a single static binary to avoid runtime dependencies, we deliberately chose Python to make installation ubiquitous across all OSes via PyPI, and to allow for rapid iteration and community-driven plugins.
|
|
18
|
+
|
|
19
|
+
**The Tradeoff**: You will need a Python 3.9+ runtime to use Locci, even if your project is written in Node.js, Go, or Rust.
|
|
20
|
+
|
|
21
|
+
**Recommendation**: We strongly recommend installing Locci globally via `pipx` to isolate its dependencies from your system Python:
|
|
22
|
+
```bash
|
|
23
|
+
pipx install locci
|
|
24
|
+
```
|
|
25
|
+
This gives you a globally available `locci` command that feels exactly like a static binary, without cluttering your environment.
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
# First-time setup in a repo
|
|
31
|
+
locci setup
|
|
32
|
+
|
|
33
|
+
# Daily local CI check
|
|
34
|
+
locci check
|
|
35
|
+
|
|
36
|
+
# Affected pre-push check
|
|
37
|
+
locci preflight
|
|
38
|
+
|
|
39
|
+
# Watch for file changes and incrementally rerun only affected steps
|
|
40
|
+
locci watch
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Useful commands:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
locci setup --preview # print the generated locci.yml without writing
|
|
47
|
+
locci check --dry-run # show the local execution graph
|
|
48
|
+
locci check --strict-coverage
|
|
49
|
+
locci hook install # install a managed pre-push hook
|
|
50
|
+
locci doctor # inspect required local tools
|
|
51
|
+
```
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "locci"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "A fast, local-first CI engine."
|
|
5
|
+
authors = [{name = "Locci Developers"}]
|
|
6
|
+
readme = "README.md"
|
|
7
|
+
requires-python = ">=3.9"
|
|
8
|
+
dependencies = [
|
|
9
|
+
"typer>=0.9.0",
|
|
10
|
+
"rich>=13.0.0",
|
|
11
|
+
"networkx>=3.0",
|
|
12
|
+
"pyyaml>=6.0.1",
|
|
13
|
+
"pydantic>=2.0.0",
|
|
14
|
+
"watchdog>=3.0.0",
|
|
15
|
+
"tomli>=2.0.1; python_version < '3.11'"
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
[project.optional-dependencies]
|
|
19
|
+
ai = [
|
|
20
|
+
"anthropic>=0.20.0"
|
|
21
|
+
]
|
|
22
|
+
s3 = [
|
|
23
|
+
"boto3>=1.28.0"
|
|
24
|
+
]
|
|
25
|
+
dev = [
|
|
26
|
+
"pytest>=7.0.0",
|
|
27
|
+
"pytest-asyncio"
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
[project.scripts]
|
|
31
|
+
locci = "locci.cli:app"
|
|
32
|
+
|
|
33
|
+
[build-system]
|
|
34
|
+
requires = ["hatchling"]
|
|
35
|
+
build-backend = "hatchling.build"
|
|
36
|
+
|
|
37
|
+
[tool.pytest.ini_options]
|
|
38
|
+
pythonpath = ["src"]
|
|
39
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
import random
|
|
4
|
+
import tempfile
|
|
5
|
+
import time
|
|
6
|
+
|
|
7
|
+
from locci.analyzer import Task
|
|
8
|
+
from locci.orchestrator import Orchestrator
|
|
9
|
+
|
|
10
|
+
async def main():
|
|
11
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
12
|
+
project_root = Path(tmp)
|
|
13
|
+
cache_db = project_root / "cache.db"
|
|
14
|
+
|
|
15
|
+
# Create 500 tasks
|
|
16
|
+
tasks = []
|
|
17
|
+
for i in range(500):
|
|
18
|
+
deps = []
|
|
19
|
+
if i > 0:
|
|
20
|
+
num_deps = random.randint(1, min(i, 3))
|
|
21
|
+
deps = [f"task_{random.randint(0, i-1)}" for _ in range(num_deps)]
|
|
22
|
+
|
|
23
|
+
task = Task(
|
|
24
|
+
name=f"task_{i}",
|
|
25
|
+
cmd=["bash", "-c", f"echo 'Running task {i} with a bunch of output to bloat cache' && sleep 0.1"],
|
|
26
|
+
depends_on=deps,
|
|
27
|
+
input_globs=[]
|
|
28
|
+
)
|
|
29
|
+
tasks.append(task)
|
|
30
|
+
|
|
31
|
+
print(f"Generated {len(tasks)} tasks.")
|
|
32
|
+
|
|
33
|
+
orch = Orchestrator(
|
|
34
|
+
project_root=project_root,
|
|
35
|
+
cache_db=cache_db,
|
|
36
|
+
no_cache=True,
|
|
37
|
+
jobs=100
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
start = time.time()
|
|
41
|
+
success = await orch.run(tasks)
|
|
42
|
+
end = time.time()
|
|
43
|
+
|
|
44
|
+
print(f"Success: {success}")
|
|
45
|
+
print(f"Time: {end - start:.2f}s")
|
|
46
|
+
|
|
47
|
+
if not success:
|
|
48
|
+
import sys
|
|
49
|
+
sys.exit(1)
|
|
50
|
+
|
|
51
|
+
if __name__ == "__main__":
|
|
52
|
+
asyncio.run(main())
|
|
File without changes
|