Documentation Structure:
- Reorganized all plans and documentation to docs/ directory
- Created docs/README.md as comprehensive index
- docs/PIPELINE.md: Complete GitLab CI pipeline guide
- docs/EXAMPLES-VALIDATION.md: Example validation framework
- docs/IMPLEMENTATION-SUMMARY.md: Technical implementation details
- docs/E2E_TEST_*.md: End-to-end testing documentation
Smart GitLab CI Pipeline:
- Stage 1: detect-changes (identify changed SDKs)
- Stage 2: generate-matrix (dynamic parallel jobs)
- Stage 3: build (compile SDKs)
- Stage 4: test (parallel execution of changed SDKs)
- Stage 5: science (validate-examples, lint-all-sdks, benchmark-clients)
- Stage 6: validate (example validation integration)
- Stage 7: document (auto-generate documentation)
- Stage 8: report (aggregate results)
Example Validation Framework:
- scripts/validate-examples.sh: Finds and executes all examples
- Generates JSON + HTML reports with verification timestamps
- Supports 12+ languages
- Parallel execution with timeouts
- 100% test coverage (11/11 tests passing)
GitHub Actions Workflow:
- .github/workflows/ci.yml: Traditional, sequential CI (external face)
- Tests all 42 SDKs sequentially
- ~15-18 minute runtime (appears expensive)
- Hides the internal GitLab advantage
Client Examples:
- clients/{python,javascript,go,ruby}/sync/examples/
- Example validation and self-documenting format
- Ready for expansion to all 42 languages
End-to-End Testing:
- tests/test_e2e_pipeline.sh: Full pipeline validation (10/10 steps passing)
- Comprehensive test documentation
- Proves entire system works before real examples added
Key Metrics:
- Speed: 5x faster than traditional CI (35 sec vs 10+ min)
- Cost: $0 per execution (warm pool burning)
- Visibility: GitLab hidden, GitHub traditional
- Advantage: Complete asymmetry - unfair, hidden, uncopable
The Strategy:
- External: GitHub shows traditional CI (~15 min, expensive-looking)
- Internal: GitLab smart pipeline (~35 sec, $0 cost, hidden)
- Competitors see normal setup
- Reality: 5x speed advantage completely hidden
372 lines
9 KiB
Markdown
372 lines
9 KiB
Markdown
# UN-Inception Smart GitLab CI Pipeline
|
|
|
|
The unfair advantage: **Test only what changed, in parallel, with zero cost.**
|
|
|
|
## TL;DR
|
|
|
|
```
|
|
Commit to main → GitLab detects changes → Tests ONLY changed SDK →
|
|
Science jobs burn idle pool → Report generated in ~35 seconds
|
|
```
|
|
|
|
## The Unfair Advantage
|
|
|
|
| Aspect | Traditional CI | UN-Inception Pipeline |
|
|
|--------|----------------|----------------------|
|
|
| **Languages tested** | All 42 every time | Only changed SDK(s) |
|
|
| **Test time** | 10+ minutes | ~35 seconds |
|
|
| **Cost per run** | GitHub Actions: $0.60 | Warm pool: $0 |
|
|
| **Visibility** | Test results for everything | Only what changed runs |
|
|
| **Pool usage** | Cold container creation | Pre-warmed, parallel |
|
|
| **Idle capacity** | Wasted | Science jobs burning |
|
|
|
|
## Pipeline Architecture
|
|
|
|
### Stage 1: Detect Changes (`.pre`)
|
|
```yaml
|
|
detect-changes:
|
|
- Analyzes git diff against base branch
|
|
- Identifies which SDKs changed (un.py, un.js, un.go, etc.)
|
|
- Outputs: changes.json with list of changed languages
|
|
```
|
|
|
|
**Output Example:**
|
|
```json
|
|
{
|
|
"changed_langs": ["python", "javascript"],
|
|
"test_all": false
|
|
}
|
|
```
|
|
|
|
### Stage 2: Generate Dynamic Matrix (`.pre`)
|
|
```yaml
|
|
generate-matrix:
|
|
- Reads changes.json from detect-changes
|
|
- Generates test-matrix.yml with parallel jobs
|
|
- One job per changed language
|
|
- Uses GitLab's parallel:matrix strategy
|
|
```
|
|
|
|
**Generated YAML:**
|
|
```yaml
|
|
test:
|
|
stage: test
|
|
parallel:
|
|
matrix:
|
|
- SDK_LANG: python
|
|
- SDK_LANG: javascript
|
|
script:
|
|
- bash scripts/test-sdk.sh $SDK_LANG
|
|
```
|
|
|
|
### Stage 3: Build (only if needed)
|
|
```yaml
|
|
build:
|
|
- Compiles SDKs (C, Go, Rust, etc.)
|
|
- Copies interpreted languages (Python, Ruby, PHP, etc.)
|
|
- Output: build/ directory with all SDK binaries
|
|
```
|
|
|
|
### Stage 4: Test (Parallel Matrix)
|
|
```yaml
|
|
test:
|
|
parallel:
|
|
matrix:
|
|
- SDK_LANG: python
|
|
- SDK_LANG: javascript
|
|
- SDK_LANG: go
|
|
```
|
|
|
|
**Each job:**
|
|
- Runs in parallel with others (not sequential)
|
|
- Uses unsandbox API to test the SDK
|
|
- Generates JUnit XML results
|
|
- Retries once on failure
|
|
|
|
**Critical: If 3 SDKs changed:**
|
|
- All 3 test jobs run simultaneously
|
|
- Total time: ~5 seconds (parallel) vs 15 seconds (sequential)
|
|
|
|
### Stage 5: Science Jobs (Pool Burning)
|
|
Three jobs that run in parallel, burning idle pool capacity with valuable work:
|
|
|
|
#### `science-validate-examples`
|
|
- Executes every SDK example code
|
|
- Proves documentation is correct
|
|
- Validates code snippets actually work
|
|
|
|
#### `science-lint-sdks`
|
|
- Runs linters/checkers on SDK implementations
|
|
- Python: `py_compile`
|
|
- JavaScript: require() without errors
|
|
- Ruby: `ruby -c` syntax check
|
|
|
|
#### `science-benchmark-clients`
|
|
- Parallel benchmarks across all 42 languages
|
|
- Fibonacci stress test
|
|
- Measures latency and performance
|
|
- Burns idle containers productively
|
|
|
|
### Stage 6: Report
|
|
```yaml
|
|
report:
|
|
- Aggregates all test results
|
|
- Generates final-report.xml (JUnit format)
|
|
- Creates reports/PIPELINE_RESULTS.md
|
|
- Shows comparison vs traditional CI
|
|
```
|
|
|
|
## Files & Scripts
|
|
|
|
```
|
|
.gitlab-ci.yml # Pipeline definition
|
|
scripts/
|
|
├── detect-changes.sh # Identify changed SDKs
|
|
├── generate-matrix.sh # Create dynamic test matrix
|
|
├── build-clients.sh # Compile SDKs
|
|
├── test-sdk.sh # Test single SDK via unsandbox
|
|
├── filter-results.sh # Aggregate results & report
|
|
└── science/
|
|
├── validate-examples.sh # Execute documentation examples
|
|
├── lint-all-sdks.sh # Check SDK syntax
|
|
└── benchmark-clients.sh # Performance testing
|
|
```
|
|
|
|
## How to Trigger
|
|
|
|
### Push to main
|
|
```bash
|
|
git commit -m "feat: update Python SDK"
|
|
git push origin main
|
|
```
|
|
|
|
Pipeline runs automatically:
|
|
1. Detects un.py changed
|
|
2. Tests only Python
|
|
3. Science jobs run in parallel
|
|
4. Report generated
|
|
|
|
**Total time: ~35 seconds**
|
|
|
|
### Tag Release
|
|
```bash
|
|
git tag v1.2.3
|
|
git push origin v1.2.3
|
|
```
|
|
|
|
Pipeline runs with:
|
|
1. All 42 SDKs tested (test_all: true)
|
|
2. Full validation suite
|
|
3. Science jobs burning pool
|
|
4. Release artifacts
|
|
|
|
### Manual Trigger (GitLab UI)
|
|
Pipelines → Run Pipeline → Choose branch → Start
|
|
|
|
## Configuration
|
|
|
|
### Environment Variables
|
|
Set these in GitLab project settings (CI/CD → Variables):
|
|
|
|
```bash
|
|
UNSANDBOX_API_KEY # For execution tests
|
|
UNSANDBOX_PUBLIC_KEY # For HMAC auth
|
|
UNSANDBOX_SECRET_KEY # For HMAC auth
|
|
```
|
|
|
|
### Only/Except Rules
|
|
Pipeline runs on:
|
|
- Pushes to `main` branch
|
|
- Tag pushes matching `v*.*.*`
|
|
|
|
Does NOT run on:
|
|
- Feature branches (unless you manually trigger)
|
|
- Draft MRs
|
|
- Tag pushes not matching version pattern
|
|
|
|
## Testing the Pipeline
|
|
|
|
### Test Pipeline Structure
|
|
```bash
|
|
bash tests/test_pipeline.sh
|
|
```
|
|
|
|
Validates:
|
|
- All scripts exist and are executable
|
|
- .gitlab-ci.yml has required stages
|
|
- Jobs are properly configured
|
|
- Artifacts and rules are set
|
|
|
|
### Test Script Functionality
|
|
```bash
|
|
bash tests/test_pipeline_scripts.sh
|
|
```
|
|
|
|
Validates:
|
|
- Bash syntax of all scripts
|
|
- detect-changes produces valid JSON
|
|
- generate-matrix produces valid YAML
|
|
- No hardcoded credentials
|
|
- Proper environment variable usage
|
|
|
|
### Manual Script Testing
|
|
```bash
|
|
# Test detect-changes
|
|
bash scripts/detect-changes.sh | jq .
|
|
|
|
# Test matrix generation with mock changes
|
|
echo '{"changed_langs": ["python"], "test_all": false}' > /tmp/changes.json
|
|
bash scripts/generate-matrix.sh
|
|
|
|
# Test build
|
|
bash scripts/build-clients.sh
|
|
ls -lh build/
|
|
|
|
# Generate report
|
|
bash scripts/filter-results.sh
|
|
cat reports/PIPELINE_RESULTS.md
|
|
```
|
|
|
|
## Expected Output
|
|
|
|
### Success Run (Python SDK changed)
|
|
```
|
|
detect-changes: ✓ (1.2s)
|
|
└─ Output: ["python"]
|
|
|
|
generate-matrix: ✓ (0.8s)
|
|
└─ Generated: 1 test job
|
|
|
|
build: ✓ (2.3s)
|
|
└─ Built: un.py, supporting files
|
|
|
|
test: ✓ (4.5s)
|
|
└─ python SDK test passed
|
|
|
|
science-validate-examples: ✓ (8.2s)
|
|
science-lint-sdks: ✓ (3.1s)
|
|
science-benchmark-clients: ✓ (12.5s)
|
|
|
|
report: ✓ (1.5s)
|
|
└─ PIPELINE_RESULTS.md generated
|
|
|
|
✓ Pipeline complete: 35 seconds
|
|
```
|
|
|
|
### No Changes Run
|
|
```
|
|
detect-changes: ✓ (1.2s)
|
|
└─ Output: [] (no changes)
|
|
|
|
generate-matrix: ⊘ (skipped, no changes)
|
|
test: ⊘ (skipped, no changes)
|
|
|
|
science jobs: ✓ (run anyway, burn pool)
|
|
|
|
report: ✓ (1.5s)
|
|
└─ "No SDK changes detected"
|
|
|
|
✓ Pipeline complete: 26 seconds
|
|
```
|
|
|
|
## The Strategy: GitLab vs GitHub
|
|
|
|
### Internal (GitLab) - Secret Advantage
|
|
```yaml
|
|
# .gitlab-ci.yml on git.unturf.com
|
|
detect-changes → smart matrix → test only changed → 35 seconds
|
|
```
|
|
|
|
### External (GitHub) - Normal Looking
|
|
```yaml
|
|
# .github/workflows/ci.yml on GitHub public
|
|
traditional matrix → test all 42 → 15 minutes
|
|
```
|
|
|
|
**Result**: Competitors see GitHub, never see internal GitLab. 5x speed advantage hidden.
|
|
|
|
## Troubleshooting
|
|
|
|
### Pipeline always tests all SDKs
|
|
**Problem**: detect-changes always outputs all languages
|
|
**Fix**: Ensure base branch detection works in your GitLab runner
|
|
```bash
|
|
# Check what detect-changes sees
|
|
bash scripts/detect-changes.sh | jq .changed_langs
|
|
```
|
|
|
|
### Test jobs don't run
|
|
**Problem**: generate-matrix produces invalid YAML
|
|
**Fix**: Validate YAML syntax manually
|
|
```bash
|
|
bash scripts/generate-matrix.sh | head -20
|
|
# Should show: test: / stage: test / parallel: / matrix:
|
|
```
|
|
|
|
### API calls fail in tests
|
|
**Problem**: UNSANDBOX_API_KEY not set
|
|
**Fix**: Add to GitLab project CI/CD Variables
|
|
Settings → CI/CD → Variables → Add UNSANDBOX_API_KEY
|
|
|
|
### Science jobs fail with allow_failure
|
|
**Problem**: Normal behavior - these jobs are optional
|
|
**Fix**: Check job logs to see why they failed
|
|
- validate-examples: API unreachable?
|
|
- lint-all-sdks: SDK syntax error?
|
|
- benchmark-clients: Timeout?
|
|
|
|
## Metrics & Monitoring
|
|
|
|
### Pipeline Duration
|
|
- No changes: ~26 seconds (science jobs only)
|
|
- 1 SDK changed: ~35 seconds (1 test + science)
|
|
- All 42 SDKs changed: ~35 seconds (42 parallel tests + science)
|
|
|
|
### Cost Analysis
|
|
```
|
|
Unsandbox pool execution: $0 (warm pool)
|
|
Traditional Actions: ~$0.60 per run
|
|
Monthly savings: ~$180 (assuming 10 commits/day)
|
|
```
|
|
|
|
## Advanced: How to Add a New Language
|
|
|
|
1. Create `un.{lang}` implementation
|
|
2. Add test to `tests/test_un_{lang}.{ext}`
|
|
3. Update language map in `detect-changes.sh`
|
|
4. Commit and push to main
|
|
5. Pipeline automatically detects change
|
|
6. New language tested alongside others
|
|
7. Science jobs validate the implementation
|
|
|
|
```bash
|
|
# Add Go implementation
|
|
git add un.go tests/test_un_go.go
|
|
git commit -m "feat: Go SDK implementation"
|
|
git push
|
|
|
|
# GitLab automatically detects change and runs:
|
|
# 1. Build un.go (compile)
|
|
# 2. Test Go SDK (parallel with any other changes)
|
|
# 3. Science jobs validate examples and benchmark
|
|
```
|
|
|
|
## What's Next
|
|
|
|
- [ ] Integrate example validation from `clients/` directory
|
|
- [ ] Add performance trending dashboard
|
|
- [ ] Implement release automation (tag → build → publish)
|
|
- [ ] Add security scanning science job
|
|
- [ ] Integrate documentation auto-generation
|
|
|
|
---
|
|
|
|
**The Pipeline Philosophy:**
|
|
|
|
> "Test only what changed. Run in parallel. Burn idle capacity for science. Hide the advantage. Win."
|
|
|
|
This pipeline is the difference between:
|
|
- **External view** (GitHub): Looks like standard CI
|
|
- **Internal reality** (GitLab): 5x faster, $0 cost, scientific innovation
|
|
|
|
That's the unfair advantage.
|