tripwire-py 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.
- tripwire_py-0.2.0/.github/ISSUE_TEMPLATE/bug_report.md +50 -0
- tripwire_py-0.2.0/.github/ISSUE_TEMPLATE/feature_request.md +41 -0
- tripwire_py-0.2.0/.github/pull_request_template.md +75 -0
- tripwire_py-0.2.0/.github/scripts/validate_cli.sh +460 -0
- tripwire_py-0.2.0/.github/workflows/ci.yml +267 -0
- tripwire_py-0.2.0/.github/workflows/release.yml +613 -0
- tripwire_py-0.2.0/.github/workflows/security.yml +180 -0
- tripwire_py-0.2.0/.github/workflows/status.yml +24 -0
- tripwire_py-0.2.0/.gitignore +14 -0
- tripwire_py-0.2.0/.pre-commit-config.yaml +48 -0
- tripwire_py-0.2.0/LICENSE +21 -0
- tripwire_py-0.2.0/Makefile +141 -0
- tripwire_py-0.2.0/PKG-INFO +1113 -0
- tripwire_py-0.2.0/README.md +1053 -0
- tripwire_py-0.2.0/bandit.yaml +25 -0
- tripwire_py-0.2.0/benchmarks/README.md +124 -0
- tripwire_py-0.2.0/benchmarks/performance.py +370 -0
- tripwire_py-0.2.0/benchmarks/results.txt +27 -0
- tripwire_py-0.2.0/docs/EnvSync.md +1050 -0
- tripwire_py-0.2.0/docs/audit.md +829 -0
- tripwire_py-0.2.0/examples/README.md +232 -0
- tripwire_py-0.2.0/examples/advanced_usage.py +107 -0
- tripwire_py-0.2.0/examples/audit_example.txt +299 -0
- tripwire_py-0.2.0/examples/basic_usage.py +198 -0
- tripwire_py-0.2.0/examples/cli_workflow.md +261 -0
- tripwire_py-0.2.0/examples/custom_validators.py +121 -0
- tripwire_py-0.2.0/examples/quickstart.py +100 -0
- tripwire_py-0.2.0/pyproject.toml +175 -0
- tripwire_py-0.2.0/scripts/release.py +244 -0
- tripwire_py-0.2.0/scripts/setup-dev.py +267 -0
- tripwire_py-0.2.0/scripts/test_package.sh +90 -0
- tripwire_py-0.2.0/src/tripwire/__init__.py +45 -0
- tripwire_py-0.2.0/src/tripwire/branding.py +111 -0
- tripwire_py-0.2.0/src/tripwire/cli.py +1453 -0
- tripwire_py-0.2.0/src/tripwire/config.py +322 -0
- tripwire_py-0.2.0/src/tripwire/core.py +356 -0
- tripwire_py-0.2.0/src/tripwire/exceptions.py +220 -0
- tripwire_py-0.2.0/src/tripwire/git_audit.py +644 -0
- tripwire_py-0.2.0/src/tripwire/parser.py +447 -0
- tripwire_py-0.2.0/src/tripwire/py.typed +0 -0
- tripwire_py-0.2.0/src/tripwire/scanner.py +358 -0
- tripwire_py-0.2.0/src/tripwire/secrets.py +962 -0
- tripwire_py-0.2.0/src/tripwire/validation.py +562 -0
- tripwire_py-0.2.0/tests/__init__.py +1 -0
- tripwire_py-0.2.0/tests/conftest.py +95 -0
- tripwire_py-0.2.0/tests/test_audit_auto_detection.py +255 -0
- tripwire_py-0.2.0/tests/test_cli_validation.py +687 -0
- tripwire_py-0.2.0/tests/test_coercion.py +288 -0
- tripwire_py-0.2.0/tests/test_config.py +382 -0
- tripwire_py-0.2.0/tests/test_core.py +236 -0
- tripwire_py-0.2.0/tests/test_git_audit.py +779 -0
- tripwire_py-0.2.0/tests/test_integration.py +412 -0
- tripwire_py-0.2.0/tests/test_interpolation.py +300 -0
- tripwire_py-0.2.0/tests/test_parser.py +377 -0
- tripwire_py-0.2.0/tests/test_scanner.py +433 -0
- tripwire_py-0.2.0/tests/test_secrets.py +799 -0
- tripwire_py-0.2.0/tests/test_validation.py +369 -0
- tripwire_py-0.2.0/tests/test_validation_concurrency.py +414 -0
- tripwire_py-0.2.0/tests/test_validator_plugins.py +416 -0
- tripwire_py-0.2.0/uv.lock +1687 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Bug report
|
|
3
|
+
about: Create a report to help us improve TripWire
|
|
4
|
+
title: '[BUG] '
|
|
5
|
+
labels: bug
|
|
6
|
+
assignees: ''
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Bug Description
|
|
10
|
+
A clear and concise description of what the bug is.
|
|
11
|
+
|
|
12
|
+
## To Reproduce
|
|
13
|
+
Steps to reproduce the behavior:
|
|
14
|
+
1. Go to '...'
|
|
15
|
+
2. Run command '...'
|
|
16
|
+
3. See error
|
|
17
|
+
|
|
18
|
+
## Expected Behavior
|
|
19
|
+
A clear and concise description of what you expected to happen.
|
|
20
|
+
|
|
21
|
+
## Actual Behavior
|
|
22
|
+
A clear and concise description of what actually happened.
|
|
23
|
+
|
|
24
|
+
## Environment
|
|
25
|
+
- OS: [e.g. Ubuntu 20.04, macOS 12.0, Windows 10]
|
|
26
|
+
- Python version: [e.g. 3.9.7]
|
|
27
|
+
- TripWire version: [e.g. 0.1.0]
|
|
28
|
+
- Installation method: [e.g. pip, conda, from source]
|
|
29
|
+
|
|
30
|
+
## Code Example
|
|
31
|
+
```python
|
|
32
|
+
# Minimal code example that reproduces the issue
|
|
33
|
+
from tripwire import env
|
|
34
|
+
|
|
35
|
+
# Your code here
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Error Message
|
|
39
|
+
```
|
|
40
|
+
# Paste the full error message here
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Additional Context
|
|
44
|
+
Add any other context about the problem here.
|
|
45
|
+
|
|
46
|
+
## Checklist
|
|
47
|
+
- [ ] I have searched existing issues to avoid duplicates
|
|
48
|
+
- [ ] I have provided a minimal code example
|
|
49
|
+
- [ ] I have included the full error message
|
|
50
|
+
- [ ] I have specified my environment details
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Feature request
|
|
3
|
+
about: Suggest an idea for TripWire
|
|
4
|
+
title: '[FEATURE] '
|
|
5
|
+
labels: enhancement
|
|
6
|
+
assignees: ''
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Feature Description
|
|
10
|
+
A clear and concise description of the feature you'd like to see.
|
|
11
|
+
|
|
12
|
+
## Problem Statement
|
|
13
|
+
What problem does this feature solve? What pain point does it address?
|
|
14
|
+
|
|
15
|
+
## Proposed Solution
|
|
16
|
+
A clear and concise description of what you want to happen.
|
|
17
|
+
|
|
18
|
+
## Alternative Solutions
|
|
19
|
+
A clear and concise description of any alternative solutions or features you've considered.
|
|
20
|
+
|
|
21
|
+
## Use Case
|
|
22
|
+
Describe a specific use case where this feature would be helpful:
|
|
23
|
+
|
|
24
|
+
```python
|
|
25
|
+
# Example of how you'd like to use this feature
|
|
26
|
+
from tripwire import env
|
|
27
|
+
|
|
28
|
+
# Your desired usage
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Additional Context
|
|
32
|
+
Add any other context, mockups, or examples about the feature request here.
|
|
33
|
+
|
|
34
|
+
## Implementation Ideas
|
|
35
|
+
If you have ideas about how this could be implemented, please share them.
|
|
36
|
+
|
|
37
|
+
## Checklist
|
|
38
|
+
- [ ] I have searched existing issues to avoid duplicates
|
|
39
|
+
- [ ] I have provided a clear problem statement
|
|
40
|
+
- [ ] I have described the proposed solution
|
|
41
|
+
- [ ] I have included a use case example
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
## Description
|
|
2
|
+
Brief description of the changes in this PR.
|
|
3
|
+
|
|
4
|
+
## Type of Change
|
|
5
|
+
- [ ] Bug fix (non-breaking change which fixes an issue)
|
|
6
|
+
- [ ] New feature (non-breaking change which adds functionality)
|
|
7
|
+
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
|
|
8
|
+
- [ ] Documentation update
|
|
9
|
+
- [ ] Performance improvement
|
|
10
|
+
- [ ] Code refactoring
|
|
11
|
+
- [ ] Test improvements
|
|
12
|
+
|
|
13
|
+
## Related Issues
|
|
14
|
+
Fixes #(issue number)
|
|
15
|
+
Closes #(issue number)
|
|
16
|
+
Related to #(issue number)
|
|
17
|
+
|
|
18
|
+
## Changes Made
|
|
19
|
+
- [ ] List the main changes made
|
|
20
|
+
- [ ] Include any new dependencies
|
|
21
|
+
- [ ] Note any configuration changes
|
|
22
|
+
|
|
23
|
+
## Testing
|
|
24
|
+
- [ ] Tests pass locally
|
|
25
|
+
- [ ] New tests added for new functionality
|
|
26
|
+
- [ ] Existing tests updated if needed
|
|
27
|
+
- [ ] Integration tests pass
|
|
28
|
+
- [ ] Manual testing completed
|
|
29
|
+
|
|
30
|
+
## Code Quality
|
|
31
|
+
- [ ] Code follows project style guidelines
|
|
32
|
+
- [ ] Self-review completed
|
|
33
|
+
- [ ] Code is properly commented
|
|
34
|
+
- [ ] No hardcoded values or magic numbers
|
|
35
|
+
- [ ] Error handling is appropriate
|
|
36
|
+
|
|
37
|
+
## Security
|
|
38
|
+
- [ ] No sensitive data exposed
|
|
39
|
+
- [ ] Input validation added where needed
|
|
40
|
+
- [ ] Security implications considered
|
|
41
|
+
- [ ] No new security vulnerabilities introduced
|
|
42
|
+
|
|
43
|
+
## Documentation
|
|
44
|
+
- [ ] README updated if needed
|
|
45
|
+
- [ ] API documentation updated
|
|
46
|
+
- [ ] Code comments added for complex logic
|
|
47
|
+
- [ ] Changelog updated (if applicable)
|
|
48
|
+
|
|
49
|
+
## Performance
|
|
50
|
+
- [ ] No performance regressions
|
|
51
|
+
- [ ] Performance improvements measured
|
|
52
|
+
- [ ] Memory usage considered
|
|
53
|
+
- [ ] Database queries optimized (if applicable)
|
|
54
|
+
|
|
55
|
+
## Breaking Changes
|
|
56
|
+
If this is a breaking change, describe:
|
|
57
|
+
- What breaks
|
|
58
|
+
- How to migrate
|
|
59
|
+
- Timeline for deprecation
|
|
60
|
+
|
|
61
|
+
## Screenshots/Examples
|
|
62
|
+
If applicable, add screenshots or code examples to help explain your changes.
|
|
63
|
+
|
|
64
|
+
## Checklist
|
|
65
|
+
- [ ] My code follows the style guidelines of this project
|
|
66
|
+
- [ ] I have performed a self-review of my own code
|
|
67
|
+
- [ ] I have commented my code, particularly in hard-to-understand areas
|
|
68
|
+
- [ ] I have made corresponding changes to the documentation
|
|
69
|
+
- [ ] My changes generate no new warnings
|
|
70
|
+
- [ ] I have added tests that prove my fix is effective or that my feature works
|
|
71
|
+
- [ ] New and existing unit tests pass locally with my changes
|
|
72
|
+
- [ ] Any dependent changes have been merged and published
|
|
73
|
+
|
|
74
|
+
## Additional Notes
|
|
75
|
+
Any additional information that reviewers should know.
|
|
@@ -0,0 +1,460 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Validates CLI installation in CI/CD workflows
|
|
3
|
+
# Uses behavior-based testing, not exact string matching
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# ./validate_cli.sh [expected_version]
|
|
7
|
+
#
|
|
8
|
+
# Exit codes:
|
|
9
|
+
# 0 - All validations passed
|
|
10
|
+
# 1 - One or more validations failed
|
|
11
|
+
|
|
12
|
+
set -euo pipefail
|
|
13
|
+
|
|
14
|
+
# Color output for better readability
|
|
15
|
+
RED='\033[0;31m'
|
|
16
|
+
GREEN='\033[0;32m'
|
|
17
|
+
YELLOW='\033[1;33m'
|
|
18
|
+
CYAN='\033[0;36m'
|
|
19
|
+
NC='\033[0m' # No Color
|
|
20
|
+
|
|
21
|
+
# Test result tracking
|
|
22
|
+
TESTS_PASSED=0
|
|
23
|
+
TESTS_FAILED=0
|
|
24
|
+
|
|
25
|
+
# Collect failures for summary
|
|
26
|
+
declare -a FAILED_TESTS
|
|
27
|
+
|
|
28
|
+
#######################################
|
|
29
|
+
# Helper Functions
|
|
30
|
+
#######################################
|
|
31
|
+
|
|
32
|
+
log_success() {
|
|
33
|
+
echo -e "${GREEN}✓${NC} $1"
|
|
34
|
+
((TESTS_PASSED++))
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
log_error() {
|
|
38
|
+
echo -e "${RED}✗${NC} $1"
|
|
39
|
+
((TESTS_FAILED++))
|
|
40
|
+
FAILED_TESTS+=("$1")
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
log_info() {
|
|
44
|
+
echo -e "${CYAN}→${NC} $1"
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
log_section() {
|
|
48
|
+
echo ""
|
|
49
|
+
echo -e "${YELLOW}===${NC} $1"
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
#######################################
|
|
53
|
+
# Validation Tests
|
|
54
|
+
#######################################
|
|
55
|
+
|
|
56
|
+
test_command_exists() {
|
|
57
|
+
log_info "Testing: tripwire command is available in PATH"
|
|
58
|
+
|
|
59
|
+
if command -v tripwire &> /dev/null; then
|
|
60
|
+
log_success "tripwire command found in PATH"
|
|
61
|
+
return 0
|
|
62
|
+
else
|
|
63
|
+
log_error "tripwire command not found in PATH"
|
|
64
|
+
return 1
|
|
65
|
+
fi
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
test_basic_execution() {
|
|
69
|
+
log_info "Testing: Basic command execution (--help)"
|
|
70
|
+
|
|
71
|
+
if tripwire --help > /dev/null 2>&1; then
|
|
72
|
+
log_success "tripwire --help executes successfully"
|
|
73
|
+
return 0
|
|
74
|
+
else
|
|
75
|
+
log_error "tripwire --help failed to execute"
|
|
76
|
+
return 1
|
|
77
|
+
fi
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
test_version_flag() {
|
|
81
|
+
local expected_version="$1"
|
|
82
|
+
log_info "Testing: Version flag (expecting: $expected_version)"
|
|
83
|
+
|
|
84
|
+
# Capture version output
|
|
85
|
+
local version_output
|
|
86
|
+
if ! version_output=$(tripwire --version 2>&1); then
|
|
87
|
+
log_error "tripwire --version failed to execute"
|
|
88
|
+
return 1
|
|
89
|
+
fi
|
|
90
|
+
|
|
91
|
+
# Extract version with flexible regex (handles various formats)
|
|
92
|
+
if [[ $version_output =~ ([0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?) ]]; then
|
|
93
|
+
local actual_version="${BASH_REMATCH[1]}"
|
|
94
|
+
|
|
95
|
+
if [ "$actual_version" == "$expected_version" ]; then
|
|
96
|
+
log_success "Version matches: $actual_version"
|
|
97
|
+
return 0
|
|
98
|
+
else
|
|
99
|
+
log_error "Version mismatch: got '$actual_version', expected '$expected_version'"
|
|
100
|
+
return 1
|
|
101
|
+
fi
|
|
102
|
+
else
|
|
103
|
+
log_error "Could not extract version from output: $version_output"
|
|
104
|
+
return 1
|
|
105
|
+
fi
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
test_help_structure() {
|
|
109
|
+
log_info "Testing: Help output structure (not exact text)"
|
|
110
|
+
|
|
111
|
+
local help_output
|
|
112
|
+
if ! help_output=$(tripwire --help 2>&1); then
|
|
113
|
+
log_error "Failed to get help output"
|
|
114
|
+
return 1
|
|
115
|
+
fi
|
|
116
|
+
|
|
117
|
+
# Test structural elements exist (case-insensitive)
|
|
118
|
+
local output_lower
|
|
119
|
+
output_lower=$(echo "$help_output" | tr '[:upper:]' '[:lower:]')
|
|
120
|
+
|
|
121
|
+
local has_usage=false
|
|
122
|
+
local has_options=false
|
|
123
|
+
local has_program_name=false
|
|
124
|
+
|
|
125
|
+
[[ $output_lower =~ "usage:" ]] && has_usage=true
|
|
126
|
+
[[ $output_lower =~ "options:" ]] && has_options=true
|
|
127
|
+
[[ $output_lower =~ "tripwire" ]] && has_program_name=true
|
|
128
|
+
|
|
129
|
+
if $has_usage && $has_options && $has_program_name; then
|
|
130
|
+
log_success "Help output has expected structure (usage, options, program name)"
|
|
131
|
+
return 0
|
|
132
|
+
else
|
|
133
|
+
log_error "Help output missing expected structure"
|
|
134
|
+
[[ $has_usage == false ]] && echo " Missing: Usage section"
|
|
135
|
+
[[ $has_options == false ]] && echo " Missing: Options section"
|
|
136
|
+
[[ $has_program_name == false ]] && echo " Missing: Program name"
|
|
137
|
+
return 1
|
|
138
|
+
fi
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
test_help_not_empty() {
|
|
142
|
+
log_info "Testing: Help output is substantial (not empty)"
|
|
143
|
+
|
|
144
|
+
local help_output
|
|
145
|
+
help_output=$(tripwire --help 2>&1)
|
|
146
|
+
|
|
147
|
+
local length=${#help_output}
|
|
148
|
+
|
|
149
|
+
if [ "$length" -gt 100 ]; then
|
|
150
|
+
log_success "Help output is substantial ($length characters)"
|
|
151
|
+
return 0
|
|
152
|
+
else
|
|
153
|
+
log_error "Help output too short ($length characters)"
|
|
154
|
+
return 1
|
|
155
|
+
fi
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
test_commands_available() {
|
|
159
|
+
log_info "Testing: All expected commands execute without crashing"
|
|
160
|
+
|
|
161
|
+
local commands=("init" "generate" "check" "sync" "scan" "audit" "validate" "docs")
|
|
162
|
+
local all_passed=true
|
|
163
|
+
|
|
164
|
+
for cmd in "${commands[@]}"; do
|
|
165
|
+
if tripwire "$cmd" --help > /dev/null 2>&1; then
|
|
166
|
+
# Don't log individual successes to reduce noise
|
|
167
|
+
:
|
|
168
|
+
else
|
|
169
|
+
log_error "Command failed: $cmd --help"
|
|
170
|
+
all_passed=false
|
|
171
|
+
fi
|
|
172
|
+
done
|
|
173
|
+
|
|
174
|
+
if $all_passed; then
|
|
175
|
+
log_success "All ${#commands[@]} commands available and executable"
|
|
176
|
+
return 0
|
|
177
|
+
else
|
|
178
|
+
return 1
|
|
179
|
+
fi
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
test_python_imports() {
|
|
183
|
+
log_info "Testing: Python imports work correctly"
|
|
184
|
+
|
|
185
|
+
# Run Python import test
|
|
186
|
+
if python3 - <<'EOF'
|
|
187
|
+
import sys
|
|
188
|
+
|
|
189
|
+
try:
|
|
190
|
+
# Test basic import
|
|
191
|
+
import tripwire
|
|
192
|
+
|
|
193
|
+
# Test core components
|
|
194
|
+
from tripwire import env, TripWire
|
|
195
|
+
|
|
196
|
+
# Test exceptions
|
|
197
|
+
from tripwire import (
|
|
198
|
+
TripWireError,
|
|
199
|
+
MissingVariableError,
|
|
200
|
+
ValidationError,
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
# Test validator
|
|
204
|
+
from tripwire import validator
|
|
205
|
+
|
|
206
|
+
# All imports successful
|
|
207
|
+
sys.exit(0)
|
|
208
|
+
|
|
209
|
+
except ImportError as e:
|
|
210
|
+
print(f"Import failed: {e}", file=sys.stderr)
|
|
211
|
+
sys.exit(1)
|
|
212
|
+
EOF
|
|
213
|
+
then
|
|
214
|
+
log_success "All Python imports work correctly"
|
|
215
|
+
return 0
|
|
216
|
+
else
|
|
217
|
+
log_error "Python imports failed"
|
|
218
|
+
return 1
|
|
219
|
+
fi
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
test_version_consistency() {
|
|
223
|
+
log_info "Testing: CLI version matches package version"
|
|
224
|
+
|
|
225
|
+
# Get CLI version
|
|
226
|
+
local cli_output
|
|
227
|
+
cli_output=$(tripwire --version 2>&1)
|
|
228
|
+
|
|
229
|
+
if [[ $cli_output =~ ([0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?) ]]; then
|
|
230
|
+
local cli_version="${BASH_REMATCH[1]}"
|
|
231
|
+
|
|
232
|
+
# Get package version
|
|
233
|
+
local pkg_version
|
|
234
|
+
pkg_version=$(python3 -c "import tripwire; print(tripwire.__version__)" 2>&1)
|
|
235
|
+
|
|
236
|
+
if [ "$cli_version" == "$pkg_version" ]; then
|
|
237
|
+
log_success "CLI version matches package version: $cli_version"
|
|
238
|
+
return 0
|
|
239
|
+
else
|
|
240
|
+
log_error "Version mismatch: CLI=$cli_version, Package=$pkg_version"
|
|
241
|
+
return 1
|
|
242
|
+
fi
|
|
243
|
+
else
|
|
244
|
+
log_error "Could not extract CLI version"
|
|
245
|
+
return 1
|
|
246
|
+
fi
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
test_functional_workflow() {
|
|
250
|
+
log_info "Testing: Functional workflow (init creates files)"
|
|
251
|
+
|
|
252
|
+
# Create temporary directory
|
|
253
|
+
local test_dir
|
|
254
|
+
test_dir=$(mktemp -d)
|
|
255
|
+
|
|
256
|
+
# Run test in isolated environment
|
|
257
|
+
(
|
|
258
|
+
cd "$test_dir" || exit 1
|
|
259
|
+
|
|
260
|
+
# Test init command
|
|
261
|
+
if ! tripwire init --project-type=cli > /dev/null 2>&1; then
|
|
262
|
+
echo "init command failed" >&2
|
|
263
|
+
exit 1
|
|
264
|
+
fi
|
|
265
|
+
|
|
266
|
+
# Check files were created
|
|
267
|
+
if [ ! -f ".env" ]; then
|
|
268
|
+
echo ".env not created" >&2
|
|
269
|
+
exit 1
|
|
270
|
+
fi
|
|
271
|
+
|
|
272
|
+
if [ ! -f ".env.example" ]; then
|
|
273
|
+
echo ".env.example not created" >&2
|
|
274
|
+
exit 1
|
|
275
|
+
fi
|
|
276
|
+
|
|
277
|
+
# Check files have content
|
|
278
|
+
if [ ! -s ".env" ]; then
|
|
279
|
+
echo ".env is empty" >&2
|
|
280
|
+
exit 1
|
|
281
|
+
fi
|
|
282
|
+
|
|
283
|
+
if [ ! -s ".env.example" ]; then
|
|
284
|
+
echo ".env.example is empty" >&2
|
|
285
|
+
exit 1
|
|
286
|
+
fi
|
|
287
|
+
|
|
288
|
+
exit 0
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
local result=$?
|
|
292
|
+
|
|
293
|
+
# Cleanup
|
|
294
|
+
rm -rf "$test_dir"
|
|
295
|
+
|
|
296
|
+
if [ $result -eq 0 ]; then
|
|
297
|
+
log_success "init command creates expected files with content"
|
|
298
|
+
return 0
|
|
299
|
+
else
|
|
300
|
+
log_error "Functional workflow test failed"
|
|
301
|
+
return 1
|
|
302
|
+
fi
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
test_json_output_valid() {
|
|
306
|
+
log_info "Testing: Commands with --json produce valid JSON"
|
|
307
|
+
|
|
308
|
+
local test_dir
|
|
309
|
+
test_dir=$(mktemp -d)
|
|
310
|
+
|
|
311
|
+
(
|
|
312
|
+
cd "$test_dir" || exit 1
|
|
313
|
+
|
|
314
|
+
# Create test files
|
|
315
|
+
echo "VAR1=value1" > .env
|
|
316
|
+
echo "VAR1=" > .env.example
|
|
317
|
+
echo "VAR2=" >> .env.example
|
|
318
|
+
|
|
319
|
+
# Test check --json
|
|
320
|
+
local json_output
|
|
321
|
+
json_output=$(tripwire check --json 2>&1)
|
|
322
|
+
|
|
323
|
+
# Validate JSON with Python
|
|
324
|
+
python3 - <<EOF
|
|
325
|
+
import sys
|
|
326
|
+
import json
|
|
327
|
+
|
|
328
|
+
try:
|
|
329
|
+
data = json.loads('''$json_output''')
|
|
330
|
+
if not isinstance(data, dict):
|
|
331
|
+
print("JSON output is not a dictionary", file=sys.stderr)
|
|
332
|
+
sys.exit(1)
|
|
333
|
+
sys.exit(0)
|
|
334
|
+
except json.JSONDecodeError as e:
|
|
335
|
+
print(f"Invalid JSON: {e}", file=sys.stderr)
|
|
336
|
+
sys.exit(1)
|
|
337
|
+
EOF
|
|
338
|
+
)
|
|
339
|
+
|
|
340
|
+
local result=$?
|
|
341
|
+
rm -rf "$test_dir"
|
|
342
|
+
|
|
343
|
+
if [ $result -eq 0 ]; then
|
|
344
|
+
log_success "Commands produce valid JSON output"
|
|
345
|
+
return 0
|
|
346
|
+
else
|
|
347
|
+
log_error "JSON output validation failed"
|
|
348
|
+
return 1
|
|
349
|
+
fi
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
test_error_handling() {
|
|
353
|
+
log_info "Testing: CLI handles errors gracefully (no crashes)"
|
|
354
|
+
|
|
355
|
+
local all_passed=true
|
|
356
|
+
|
|
357
|
+
# Test 1: Invalid command
|
|
358
|
+
if tripwire invalid_command_xyz > /dev/null 2>&1; then
|
|
359
|
+
# Should fail, not succeed
|
|
360
|
+
log_error "Invalid command should return non-zero exit code"
|
|
361
|
+
all_passed=false
|
|
362
|
+
fi
|
|
363
|
+
|
|
364
|
+
# Test 2: Missing file (check should handle gracefully)
|
|
365
|
+
local test_dir
|
|
366
|
+
test_dir=$(mktemp -d)
|
|
367
|
+
|
|
368
|
+
(
|
|
369
|
+
cd "$test_dir" || exit 1
|
|
370
|
+
# No .env file exists
|
|
371
|
+
tripwire check > /dev/null 2>&1
|
|
372
|
+
# Should exit gracefully (not crash)
|
|
373
|
+
exit 0
|
|
374
|
+
)
|
|
375
|
+
|
|
376
|
+
if [ $? -ne 0 ]; then
|
|
377
|
+
all_passed=false
|
|
378
|
+
fi
|
|
379
|
+
|
|
380
|
+
rm -rf "$test_dir"
|
|
381
|
+
|
|
382
|
+
if $all_passed; then
|
|
383
|
+
log_success "CLI handles errors gracefully (no crashes)"
|
|
384
|
+
return 0
|
|
385
|
+
else
|
|
386
|
+
log_error "Error handling test failed"
|
|
387
|
+
return 1
|
|
388
|
+
fi
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
#######################################
|
|
392
|
+
# Main Execution
|
|
393
|
+
#######################################
|
|
394
|
+
|
|
395
|
+
main() {
|
|
396
|
+
local expected_version="${1:-}"
|
|
397
|
+
|
|
398
|
+
echo "========================================="
|
|
399
|
+
echo "TripWire CLI Validation"
|
|
400
|
+
echo "========================================="
|
|
401
|
+
|
|
402
|
+
if [ -n "$expected_version" ]; then
|
|
403
|
+
echo "Expected version: $expected_version"
|
|
404
|
+
fi
|
|
405
|
+
|
|
406
|
+
echo ""
|
|
407
|
+
|
|
408
|
+
# Run all validation tests
|
|
409
|
+
log_section "Basic Functionality"
|
|
410
|
+
test_command_exists || true
|
|
411
|
+
test_basic_execution || true
|
|
412
|
+
test_help_structure || true
|
|
413
|
+
test_help_not_empty || true
|
|
414
|
+
|
|
415
|
+
if [ -n "$expected_version" ]; then
|
|
416
|
+
log_section "Version Validation"
|
|
417
|
+
test_version_flag "$expected_version" || true
|
|
418
|
+
test_version_consistency || true
|
|
419
|
+
fi
|
|
420
|
+
|
|
421
|
+
log_section "Command Availability"
|
|
422
|
+
test_commands_available || true
|
|
423
|
+
|
|
424
|
+
log_section "Python Integration"
|
|
425
|
+
test_python_imports || true
|
|
426
|
+
|
|
427
|
+
log_section "Functional Tests"
|
|
428
|
+
test_functional_workflow || true
|
|
429
|
+
test_json_output_valid || true
|
|
430
|
+
|
|
431
|
+
log_section "Error Handling"
|
|
432
|
+
test_error_handling || true
|
|
433
|
+
|
|
434
|
+
# Summary
|
|
435
|
+
echo ""
|
|
436
|
+
echo "========================================="
|
|
437
|
+
echo "Test Summary"
|
|
438
|
+
echo "========================================="
|
|
439
|
+
echo -e "Passed: ${GREEN}${TESTS_PASSED}${NC}"
|
|
440
|
+
echo -e "Failed: ${RED}${TESTS_FAILED}${NC}"
|
|
441
|
+
|
|
442
|
+
if [ $TESTS_FAILED -gt 0 ]; then
|
|
443
|
+
echo ""
|
|
444
|
+
echo -e "${RED}Failed tests:${NC}"
|
|
445
|
+
for test in "${FAILED_TESTS[@]}"; do
|
|
446
|
+
echo " - $test"
|
|
447
|
+
done
|
|
448
|
+
|
|
449
|
+
echo ""
|
|
450
|
+
echo -e "${RED}Validation failed${NC}"
|
|
451
|
+
exit 1
|
|
452
|
+
else
|
|
453
|
+
echo ""
|
|
454
|
+
echo -e "${GREEN}All validations passed!${NC}"
|
|
455
|
+
exit 0
|
|
456
|
+
fi
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
# Run with optional version argument
|
|
460
|
+
main "$@"
|