env-auditor 0.2.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.
- env_auditor-0.2.0/.gitignore +54 -0
- env_auditor-0.2.0/LICENSE +21 -0
- env_auditor-0.2.0/PKG-INFO +236 -0
- env_auditor-0.2.0/README.md +194 -0
- env_auditor-0.2.0/pyproject.toml +84 -0
- env_auditor-0.2.0/src/env_auditor/__init__.py +10 -0
- env_auditor-0.2.0/src/env_auditor/__main__.py +6 -0
- env_auditor-0.2.0/src/env_auditor/cli.py +389 -0
- env_auditor-0.2.0/src/env_auditor/colors.py +64 -0
- env_auditor-0.2.0/src/env_auditor/config.py +392 -0
- env_auditor-0.2.0/src/env_auditor/differ.py +61 -0
- env_auditor-0.2.0/src/env_auditor/parser.py +150 -0
- env_auditor-0.2.0/src/env_auditor/patterns.py +144 -0
- env_auditor-0.2.0/src/env_auditor/reporter.py +184 -0
- env_auditor-0.2.0/src/env_auditor/scanner.py +312 -0
- env_auditor-0.2.0/tests/__init__.py +0 -0
- env_auditor-0.2.0/tests/fixtures/env_files/comprehensive.env +13 -0
- env_auditor-0.2.0/tests/fixtures/env_files/windows.env +2 -0
- env_auditor-0.2.0/tests/fixtures/sample_project/.env.example +19 -0
- env_auditor-0.2.0/tests/fixtures/sample_project/src/cache.py +8 -0
- env_auditor-0.2.0/tests/fixtures/sample_project/src/config/app.js +9 -0
- env_auditor-0.2.0/tests/fixtures/sample_project/src/db/connection.py +9 -0
- env_auditor-0.2.0/tests/fixtures/sample_project/src/payments/webhook.py +11 -0
- env_auditor-0.2.0/tests/test_cli.py +541 -0
- env_auditor-0.2.0/tests/test_colors.py +72 -0
- env_auditor-0.2.0/tests/test_config.py +383 -0
- env_auditor-0.2.0/tests/test_differ.py +123 -0
- env_auditor-0.2.0/tests/test_main_entrypoint.py +85 -0
- env_auditor-0.2.0/tests/test_parser.py +160 -0
- env_auditor-0.2.0/tests/test_scanner.py +403 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
env/
|
|
8
|
+
venv/
|
|
9
|
+
ENV/
|
|
10
|
+
.venv/
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
*.egg-info/
|
|
24
|
+
.installed.cfg
|
|
25
|
+
*.egg
|
|
26
|
+
|
|
27
|
+
# Testing & coverage
|
|
28
|
+
.pytest_cache/
|
|
29
|
+
.coverage
|
|
30
|
+
.coverage.*
|
|
31
|
+
coverage.xml
|
|
32
|
+
htmlcov/
|
|
33
|
+
|
|
34
|
+
# Type checking
|
|
35
|
+
.mypy_cache/
|
|
36
|
+
.dmypy.json
|
|
37
|
+
|
|
38
|
+
# IDEs
|
|
39
|
+
.vscode/
|
|
40
|
+
.idea/
|
|
41
|
+
*.swp
|
|
42
|
+
*.swo
|
|
43
|
+
*~
|
|
44
|
+
|
|
45
|
+
# OS
|
|
46
|
+
.DS_Store
|
|
47
|
+
Thumbs.db
|
|
48
|
+
|
|
49
|
+
# Environment files
|
|
50
|
+
.env
|
|
51
|
+
.env.local
|
|
52
|
+
.env.production
|
|
53
|
+
.env.staging
|
|
54
|
+
config.ini
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 SemTiOne
|
|
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,236 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: env-auditor
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Audit environment variable consistency across a codebase.
|
|
5
|
+
Project-URL: Homepage, https://github.com/SemTiOne/env-auditor
|
|
6
|
+
Project-URL: Issues, https://github.com/SemTiOne/env-auditor/issues
|
|
7
|
+
License: MIT License
|
|
8
|
+
|
|
9
|
+
Copyright (c) 2026 SemTiOne
|
|
10
|
+
|
|
11
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
12
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
13
|
+
in the Software without restriction, including without limitation the rights
|
|
14
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
15
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
16
|
+
furnished to do so, subject to the following conditions:
|
|
17
|
+
|
|
18
|
+
The above copyright notice and this permission notice shall be included in all
|
|
19
|
+
copies or substantial portions of the Software.
|
|
20
|
+
|
|
21
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
22
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
23
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
24
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
25
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
26
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
27
|
+
SOFTWARE.
|
|
28
|
+
License-File: LICENSE
|
|
29
|
+
Keywords: audit,cli,devtools,dotenv,env
|
|
30
|
+
Classifier: Development Status :: 4 - Beta
|
|
31
|
+
Classifier: Environment :: Console
|
|
32
|
+
Classifier: Intended Audience :: Developers
|
|
33
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
34
|
+
Classifier: Programming Language :: Python :: 3
|
|
35
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
36
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
38
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
39
|
+
Classifier: Topic :: Utilities
|
|
40
|
+
Requires-Python: >=3.10
|
|
41
|
+
Description-Content-Type: text/markdown
|
|
42
|
+
|
|
43
|
+
# env-auditor
|
|
44
|
+
|
|
45
|
+
[](https://github.com/SemTiOne/env-auditor/actions)
|
|
46
|
+
[](https://pypi.org/project/env-auditor/)
|
|
47
|
+
[](https://pypi.org/project/env-auditor/)
|
|
48
|
+
[](LICENSE)
|
|
49
|
+
|
|
50
|
+
**Audit environment variable consistency across your codebase.** Finds vars used in code but missing from `.env.example`, stale vars nobody references anymore, and required vars with no default value — in any language.
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
$ env-auditor .
|
|
54
|
+
|
|
55
|
+
env-auditor — environment variable audit
|
|
56
|
+
──────────────────────────────────────────
|
|
57
|
+
|
|
58
|
+
✗ 3 undocumented variables (in code, missing from .env.example)
|
|
59
|
+
DATABASE_URL src/db/connection.py:14
|
|
60
|
+
STRIPE_WEBHOOK_SECRET src/payments/webhook.py:8, src/payments/webhook.py:31
|
|
61
|
+
REDIS_URL src/cache.py:22
|
|
62
|
+
|
|
63
|
+
⚠ 2 stale variables (in .env.example, not found in code)
|
|
64
|
+
OLD_PAYMENT_KEY
|
|
65
|
+
DEPRECATED_FEATURE_FLAG
|
|
66
|
+
|
|
67
|
+
○ 2 variables with no default value (empty in .env.example)
|
|
68
|
+
SECRET_KEY
|
|
69
|
+
JWT_SECRET
|
|
70
|
+
|
|
71
|
+
⚡ 1 dynamic reference (runtime key construction — cannot audit statically)
|
|
72
|
+
src/config/loader.py:45 → process.env[configKey]
|
|
73
|
+
|
|
74
|
+
──────────────────────────────────────────
|
|
75
|
+
Result: FAIL (exit code 1)
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Why
|
|
79
|
+
|
|
80
|
+
Your `.env.example` is a contract. It tells new contributors what the app needs to run. Over time that contract drifts: someone adds `process.env.NEW_KEY` to the source and forgets to document it, or removes a feature but leaves the stale key rotting in `.env.example`. `env-auditor` catches both automatically, in CI, before it becomes someone else's debugging session.
|
|
81
|
+
|
|
82
|
+
## Installation
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
pip install env-auditor
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Requires Python 3.10+. **Zero runtime dependencies** — pure stdlib.
|
|
89
|
+
|
|
90
|
+
## Usage
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
# Audit current directory against .env.example (default)
|
|
94
|
+
env-auditor
|
|
95
|
+
|
|
96
|
+
# Audit a specific project
|
|
97
|
+
env-auditor /path/to/project
|
|
98
|
+
|
|
99
|
+
# Use a different env file
|
|
100
|
+
env-auditor --env .env.production
|
|
101
|
+
|
|
102
|
+
# Multiple env files (keys merged — union)
|
|
103
|
+
env-auditor --env .env.example --env .env.staging
|
|
104
|
+
|
|
105
|
+
# Strict mode: fail on stale vars too
|
|
106
|
+
env-auditor --strict
|
|
107
|
+
|
|
108
|
+
# JSON output for tooling / dashboards
|
|
109
|
+
env-auditor --format json | jq .undocumented
|
|
110
|
+
|
|
111
|
+
# Suppress specific sections
|
|
112
|
+
env-auditor --ignore-stale --ignore-missing
|
|
113
|
+
|
|
114
|
+
# Exclude extra directories
|
|
115
|
+
env-auditor --exclude vendor --exclude third_party
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Config file
|
|
119
|
+
|
|
120
|
+
Commit a `.env-auditorrc` at your project root to persist settings for your whole team:
|
|
121
|
+
|
|
122
|
+
```toml
|
|
123
|
+
# .env-auditorrc
|
|
124
|
+
env_files = [".env.example", ".env.staging"]
|
|
125
|
+
exclude_dirs = ["vendor", "third_party"]
|
|
126
|
+
ignore_stale = false
|
|
127
|
+
strict = true
|
|
128
|
+
ignore_keys = ["CI", "HOME", "USER"]
|
|
129
|
+
required_keys = ["DATABASE_URL", "SECRET_KEY"]
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Or add it to `pyproject.toml` under `[tool.env-auditor]`:
|
|
133
|
+
|
|
134
|
+
```toml
|
|
135
|
+
[tool.env-auditor]
|
|
136
|
+
env_files = [".env.example"]
|
|
137
|
+
strict = true
|
|
138
|
+
ignore_keys = ["CI"]
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
CLI flags always override config file values.
|
|
142
|
+
|
|
143
|
+
`ignore_keys` excludes specific variable names from every category (undocumented, stale, missing values, required). `required_keys` is the inverse: names that must appear in at least one env file, always reported as a failure if absent, whether or not they're referenced in code (useful for infra-only vars like `DATABASE_URL` that no source file ever touches directly).
|
|
144
|
+
|
|
145
|
+
## Supported languages
|
|
146
|
+
|
|
147
|
+
| Language | Detected patterns |
|
|
148
|
+
|---|---|
|
|
149
|
+
| JavaScript / TypeScript | `process.env.VAR`, `process.env['VAR']`, `process.env["VAR"]` |
|
|
150
|
+
| Python | `os.environ['VAR']`, `os.environ.get('VAR')`, `os.getenv('VAR')` |
|
|
151
|
+
| Go | `os.Getenv("VAR")`, `os.LookupEnv("VAR")` |
|
|
152
|
+
| Shell | `$VAR`, `${VAR}` (`.sh`, `.bash`, `.zsh` only) |
|
|
153
|
+
| Docker | `ENV VAR`, `ARG VAR` in Dockerfiles |
|
|
154
|
+
| Ruby | `ENV['VAR']`, `ENV["VAR"]`, `ENV.fetch('VAR')` |
|
|
155
|
+
|
|
156
|
+
Dynamic references like `process.env[someVariable]` are flagged separately — they can't be statically audited.
|
|
157
|
+
|
|
158
|
+
## CLI reference
|
|
159
|
+
|
|
160
|
+
| Flag | Description | Default |
|
|
161
|
+
|---|---|---|
|
|
162
|
+
| `PATH` | Root directory to scan | `.` |
|
|
163
|
+
| `--env FILE` | Env file(s) as source of truth. Repeatable. | `.env.example` |
|
|
164
|
+
| `--config FILE` | Path to config file | auto-discover `.env-auditorrc` |
|
|
165
|
+
| `--ignore-stale` | Suppress stale variable report | off |
|
|
166
|
+
| `--ignore-missing` | Suppress empty-value report | off |
|
|
167
|
+
| `--format [text\|json]` | Output format | `text` |
|
|
168
|
+
| `--no-color` | Disable ANSI colors | off |
|
|
169
|
+
| `--exclude DIR` | Extra directories to skip. Repeatable. | — |
|
|
170
|
+
| `--strict` | Exit 1 on stale vars too | off |
|
|
171
|
+
| `--version` | Show version and exit | — |
|
|
172
|
+
|
|
173
|
+
## Exit codes
|
|
174
|
+
|
|
175
|
+
| Code | Meaning |
|
|
176
|
+
|---|---|
|
|
177
|
+
| `0` | Clean |
|
|
178
|
+
| `1` | Undocumented vars found, stale vars with `--strict`, or missing `required_keys` |
|
|
179
|
+
| `2` | Tool error — bad args, missing files, etc. |
|
|
180
|
+
|
|
181
|
+
## CI integration
|
|
182
|
+
|
|
183
|
+
Block deploys when env vars drift:
|
|
184
|
+
|
|
185
|
+
```yaml
|
|
186
|
+
# .github/workflows/deploy.yml
|
|
187
|
+
jobs:
|
|
188
|
+
env-audit:
|
|
189
|
+
runs-on: ubuntu-latest
|
|
190
|
+
steps:
|
|
191
|
+
- uses: actions/checkout@v4
|
|
192
|
+
- uses: actions/setup-python@v5
|
|
193
|
+
with: { python-version: "3.12" }
|
|
194
|
+
- run: pip install env-auditor
|
|
195
|
+
- run: env-auditor --strict
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Save the report as a CI artifact:
|
|
199
|
+
|
|
200
|
+
```yaml
|
|
201
|
+
- run: env-auditor --format json > env-auditor-report.json || true
|
|
202
|
+
- uses: actions/upload-artifact@v4
|
|
203
|
+
with:
|
|
204
|
+
name: env-auditor-report
|
|
205
|
+
path: env-auditor-report.json
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
For monorepos, run per-service:
|
|
209
|
+
|
|
210
|
+
```yaml
|
|
211
|
+
- run: env-auditor services/api --env services/api/.env.example
|
|
212
|
+
- run: env-auditor services/worker --env services/worker/.env.example
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## Security
|
|
216
|
+
|
|
217
|
+
- Symlinks are never followed
|
|
218
|
+
- Files over 1 MB are skipped (with a warning)
|
|
219
|
+
- Lines over 2000 characters are skipped (ReDoS protection)
|
|
220
|
+
- `--exclude` paths are validated to be within the scan root — path traversal rejected
|
|
221
|
+
- Actual `.env` values are never stored, logged, or printed — only key names
|
|
222
|
+
- No network calls, no telemetry, entirely local
|
|
223
|
+
|
|
224
|
+
## Development
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
git clone https://github.com/SemTiOne/env-auditor
|
|
228
|
+
cd env-auditor
|
|
229
|
+
pip install -e .
|
|
230
|
+
pip install pytest pytest-cov
|
|
231
|
+
pytest --cov=env_auditor --cov-report=term-missing
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
## License
|
|
235
|
+
|
|
236
|
+
MIT
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
# env-auditor
|
|
2
|
+
|
|
3
|
+
[](https://github.com/SemTiOne/env-auditor/actions)
|
|
4
|
+
[](https://pypi.org/project/env-auditor/)
|
|
5
|
+
[](https://pypi.org/project/env-auditor/)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
|
|
8
|
+
**Audit environment variable consistency across your codebase.** Finds vars used in code but missing from `.env.example`, stale vars nobody references anymore, and required vars with no default value — in any language.
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
$ env-auditor .
|
|
12
|
+
|
|
13
|
+
env-auditor — environment variable audit
|
|
14
|
+
──────────────────────────────────────────
|
|
15
|
+
|
|
16
|
+
✗ 3 undocumented variables (in code, missing from .env.example)
|
|
17
|
+
DATABASE_URL src/db/connection.py:14
|
|
18
|
+
STRIPE_WEBHOOK_SECRET src/payments/webhook.py:8, src/payments/webhook.py:31
|
|
19
|
+
REDIS_URL src/cache.py:22
|
|
20
|
+
|
|
21
|
+
⚠ 2 stale variables (in .env.example, not found in code)
|
|
22
|
+
OLD_PAYMENT_KEY
|
|
23
|
+
DEPRECATED_FEATURE_FLAG
|
|
24
|
+
|
|
25
|
+
○ 2 variables with no default value (empty in .env.example)
|
|
26
|
+
SECRET_KEY
|
|
27
|
+
JWT_SECRET
|
|
28
|
+
|
|
29
|
+
⚡ 1 dynamic reference (runtime key construction — cannot audit statically)
|
|
30
|
+
src/config/loader.py:45 → process.env[configKey]
|
|
31
|
+
|
|
32
|
+
──────────────────────────────────────────
|
|
33
|
+
Result: FAIL (exit code 1)
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Why
|
|
37
|
+
|
|
38
|
+
Your `.env.example` is a contract. It tells new contributors what the app needs to run. Over time that contract drifts: someone adds `process.env.NEW_KEY` to the source and forgets to document it, or removes a feature but leaves the stale key rotting in `.env.example`. `env-auditor` catches both automatically, in CI, before it becomes someone else's debugging session.
|
|
39
|
+
|
|
40
|
+
## Installation
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
pip install env-auditor
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Requires Python 3.10+. **Zero runtime dependencies** — pure stdlib.
|
|
47
|
+
|
|
48
|
+
## Usage
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# Audit current directory against .env.example (default)
|
|
52
|
+
env-auditor
|
|
53
|
+
|
|
54
|
+
# Audit a specific project
|
|
55
|
+
env-auditor /path/to/project
|
|
56
|
+
|
|
57
|
+
# Use a different env file
|
|
58
|
+
env-auditor --env .env.production
|
|
59
|
+
|
|
60
|
+
# Multiple env files (keys merged — union)
|
|
61
|
+
env-auditor --env .env.example --env .env.staging
|
|
62
|
+
|
|
63
|
+
# Strict mode: fail on stale vars too
|
|
64
|
+
env-auditor --strict
|
|
65
|
+
|
|
66
|
+
# JSON output for tooling / dashboards
|
|
67
|
+
env-auditor --format json | jq .undocumented
|
|
68
|
+
|
|
69
|
+
# Suppress specific sections
|
|
70
|
+
env-auditor --ignore-stale --ignore-missing
|
|
71
|
+
|
|
72
|
+
# Exclude extra directories
|
|
73
|
+
env-auditor --exclude vendor --exclude third_party
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Config file
|
|
77
|
+
|
|
78
|
+
Commit a `.env-auditorrc` at your project root to persist settings for your whole team:
|
|
79
|
+
|
|
80
|
+
```toml
|
|
81
|
+
# .env-auditorrc
|
|
82
|
+
env_files = [".env.example", ".env.staging"]
|
|
83
|
+
exclude_dirs = ["vendor", "third_party"]
|
|
84
|
+
ignore_stale = false
|
|
85
|
+
strict = true
|
|
86
|
+
ignore_keys = ["CI", "HOME", "USER"]
|
|
87
|
+
required_keys = ["DATABASE_URL", "SECRET_KEY"]
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Or add it to `pyproject.toml` under `[tool.env-auditor]`:
|
|
91
|
+
|
|
92
|
+
```toml
|
|
93
|
+
[tool.env-auditor]
|
|
94
|
+
env_files = [".env.example"]
|
|
95
|
+
strict = true
|
|
96
|
+
ignore_keys = ["CI"]
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
CLI flags always override config file values.
|
|
100
|
+
|
|
101
|
+
`ignore_keys` excludes specific variable names from every category (undocumented, stale, missing values, required). `required_keys` is the inverse: names that must appear in at least one env file, always reported as a failure if absent, whether or not they're referenced in code (useful for infra-only vars like `DATABASE_URL` that no source file ever touches directly).
|
|
102
|
+
|
|
103
|
+
## Supported languages
|
|
104
|
+
|
|
105
|
+
| Language | Detected patterns |
|
|
106
|
+
|---|---|
|
|
107
|
+
| JavaScript / TypeScript | `process.env.VAR`, `process.env['VAR']`, `process.env["VAR"]` |
|
|
108
|
+
| Python | `os.environ['VAR']`, `os.environ.get('VAR')`, `os.getenv('VAR')` |
|
|
109
|
+
| Go | `os.Getenv("VAR")`, `os.LookupEnv("VAR")` |
|
|
110
|
+
| Shell | `$VAR`, `${VAR}` (`.sh`, `.bash`, `.zsh` only) |
|
|
111
|
+
| Docker | `ENV VAR`, `ARG VAR` in Dockerfiles |
|
|
112
|
+
| Ruby | `ENV['VAR']`, `ENV["VAR"]`, `ENV.fetch('VAR')` |
|
|
113
|
+
|
|
114
|
+
Dynamic references like `process.env[someVariable]` are flagged separately — they can't be statically audited.
|
|
115
|
+
|
|
116
|
+
## CLI reference
|
|
117
|
+
|
|
118
|
+
| Flag | Description | Default |
|
|
119
|
+
|---|---|---|
|
|
120
|
+
| `PATH` | Root directory to scan | `.` |
|
|
121
|
+
| `--env FILE` | Env file(s) as source of truth. Repeatable. | `.env.example` |
|
|
122
|
+
| `--config FILE` | Path to config file | auto-discover `.env-auditorrc` |
|
|
123
|
+
| `--ignore-stale` | Suppress stale variable report | off |
|
|
124
|
+
| `--ignore-missing` | Suppress empty-value report | off |
|
|
125
|
+
| `--format [text\|json]` | Output format | `text` |
|
|
126
|
+
| `--no-color` | Disable ANSI colors | off |
|
|
127
|
+
| `--exclude DIR` | Extra directories to skip. Repeatable. | — |
|
|
128
|
+
| `--strict` | Exit 1 on stale vars too | off |
|
|
129
|
+
| `--version` | Show version and exit | — |
|
|
130
|
+
|
|
131
|
+
## Exit codes
|
|
132
|
+
|
|
133
|
+
| Code | Meaning |
|
|
134
|
+
|---|---|
|
|
135
|
+
| `0` | Clean |
|
|
136
|
+
| `1` | Undocumented vars found, stale vars with `--strict`, or missing `required_keys` |
|
|
137
|
+
| `2` | Tool error — bad args, missing files, etc. |
|
|
138
|
+
|
|
139
|
+
## CI integration
|
|
140
|
+
|
|
141
|
+
Block deploys when env vars drift:
|
|
142
|
+
|
|
143
|
+
```yaml
|
|
144
|
+
# .github/workflows/deploy.yml
|
|
145
|
+
jobs:
|
|
146
|
+
env-audit:
|
|
147
|
+
runs-on: ubuntu-latest
|
|
148
|
+
steps:
|
|
149
|
+
- uses: actions/checkout@v4
|
|
150
|
+
- uses: actions/setup-python@v5
|
|
151
|
+
with: { python-version: "3.12" }
|
|
152
|
+
- run: pip install env-auditor
|
|
153
|
+
- run: env-auditor --strict
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Save the report as a CI artifact:
|
|
157
|
+
|
|
158
|
+
```yaml
|
|
159
|
+
- run: env-auditor --format json > env-auditor-report.json || true
|
|
160
|
+
- uses: actions/upload-artifact@v4
|
|
161
|
+
with:
|
|
162
|
+
name: env-auditor-report
|
|
163
|
+
path: env-auditor-report.json
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
For monorepos, run per-service:
|
|
167
|
+
|
|
168
|
+
```yaml
|
|
169
|
+
- run: env-auditor services/api --env services/api/.env.example
|
|
170
|
+
- run: env-auditor services/worker --env services/worker/.env.example
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## Security
|
|
174
|
+
|
|
175
|
+
- Symlinks are never followed
|
|
176
|
+
- Files over 1 MB are skipped (with a warning)
|
|
177
|
+
- Lines over 2000 characters are skipped (ReDoS protection)
|
|
178
|
+
- `--exclude` paths are validated to be within the scan root — path traversal rejected
|
|
179
|
+
- Actual `.env` values are never stored, logged, or printed — only key names
|
|
180
|
+
- No network calls, no telemetry, entirely local
|
|
181
|
+
|
|
182
|
+
## Development
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
git clone https://github.com/SemTiOne/env-auditor
|
|
186
|
+
cd env-auditor
|
|
187
|
+
pip install -e .
|
|
188
|
+
pip install pytest pytest-cov
|
|
189
|
+
pytest --cov=env_auditor --cov-report=term-missing
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## License
|
|
193
|
+
|
|
194
|
+
MIT
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "env-auditor"
|
|
7
|
+
version = "0.2.0"
|
|
8
|
+
description = "Audit environment variable consistency across a codebase."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = { file = "LICENSE" }
|
|
12
|
+
keywords = ["cli", "env", "dotenv", "devtools", "audit"]
|
|
13
|
+
classifiers = [
|
|
14
|
+
"Development Status :: 4 - Beta",
|
|
15
|
+
"Environment :: Console",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Programming Language :: Python :: 3.10",
|
|
20
|
+
"Programming Language :: Python :: 3.11",
|
|
21
|
+
"Programming Language :: Python :: 3.12",
|
|
22
|
+
"Topic :: Software Development :: Build Tools",
|
|
23
|
+
"Topic :: Utilities",
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
# No runtime dependencies — stdlib only.
|
|
27
|
+
dependencies = []
|
|
28
|
+
|
|
29
|
+
[project.scripts]
|
|
30
|
+
env-auditor = "env_auditor.cli:main"
|
|
31
|
+
|
|
32
|
+
[project.urls]
|
|
33
|
+
Homepage = "https://github.com/SemTiOne/env-auditor"
|
|
34
|
+
Issues = "https://github.com/SemTiOne/env-auditor/issues"
|
|
35
|
+
|
|
36
|
+
[tool.hatch.build.targets.wheel]
|
|
37
|
+
packages = ["src/env_auditor"]
|
|
38
|
+
|
|
39
|
+
[tool.hatch.build.targets.sdist]
|
|
40
|
+
include = [
|
|
41
|
+
"src/",
|
|
42
|
+
"tests/",
|
|
43
|
+
"README.md",
|
|
44
|
+
"pyproject.toml",
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
# ──────────────────────────────────────────────────────────────────────────────
|
|
48
|
+
# Dev / test dependencies
|
|
49
|
+
# ──────────────────────────────────────────────────────────────────────────────
|
|
50
|
+
|
|
51
|
+
[tool.hatch.envs.default]
|
|
52
|
+
dependencies = [
|
|
53
|
+
"pytest>=7.4",
|
|
54
|
+
"pytest-cov>=4.1",
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
[tool.hatch.envs.default.scripts]
|
|
58
|
+
test = "pytest --cov=env_auditor --cov-report=term-missing {args}"
|
|
59
|
+
test-ci = "pytest --cov=env_auditor --cov-report=term-missing --cov-fail-under=85 {args}"
|
|
60
|
+
|
|
61
|
+
# ──────────────────────────────────────────────────────────────────────────────
|
|
62
|
+
# pytest configuration
|
|
63
|
+
# ──────────────────────────────────────────────────────────────────────────────
|
|
64
|
+
|
|
65
|
+
[tool.pytest.ini_options]
|
|
66
|
+
testpaths = ["tests"]
|
|
67
|
+
addopts = "-v"
|
|
68
|
+
|
|
69
|
+
# ──────────────────────────────────────────────────────────────────────────────
|
|
70
|
+
# Coverage configuration
|
|
71
|
+
# ──────────────────────────────────────────────────────────────────────────────
|
|
72
|
+
|
|
73
|
+
[tool.coverage.run]
|
|
74
|
+
source = ["env_auditor"]
|
|
75
|
+
branch = true
|
|
76
|
+
|
|
77
|
+
[tool.coverage.report]
|
|
78
|
+
exclude_lines = [
|
|
79
|
+
"pragma: no cover",
|
|
80
|
+
"if TYPE_CHECKING:",
|
|
81
|
+
"if __name__ == .__main__.:",
|
|
82
|
+
"raise NotImplementedError",
|
|
83
|
+
]
|
|
84
|
+
show_missing = true
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from importlib.metadata import version, PackageNotFoundError
|
|
4
|
+
|
|
5
|
+
try:
|
|
6
|
+
__version__: str = version("env-auditor")
|
|
7
|
+
except PackageNotFoundError: # pragma: no cover
|
|
8
|
+
__version__ = "0.0.0-dev"
|
|
9
|
+
|
|
10
|
+
__all__ = ["__version__"]
|