Skip to content

Commit 815fa8d

Browse files
Merge branch 'master' into docs-guide-rate-limit
2 parents 455fa1d + f030255 commit 815fa8d

File tree

154 files changed

+11411
-2022
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

154 files changed

+11411
-2022
lines changed

.github/workflows/build.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,16 @@ jobs:
8282
- name: Release
8383
if: "contains(github.event.head_commit.message, '[release]')"
8484
run: |
85+
bash publish.sh wave-api
86+
bash publish.sh wave-utils
8587
bash tag-and-push.sh
8688
env:
8789
GRADLE_OPTS: '-Dorg.gradle.daemon=false'
8890
AWS_ACCESS_KEY_ID: ${{secrets.TOWER_CI_AWS_ACCESS}}
8991
AWS_SECRET_ACCESS_KEY: ${{secrets.TOWER_CI_AWS_SECRET}}
92+
AWS_JAVA_V1_DISABLE_DEPRECATION_ANNOUNCEMENT: true
93+
AWS_DEFAULT_REGION: 'eu-west-1'
94+
PUBLISH_REPO_URL: "s3://maven.seqera.io/releases"
9095
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
9196
DOCKER_PAT: ${{ secrets.DOCKER_PAT }}
9297
QUAY_PAT: ${{ secrets.QUAY_PAT }}

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
Thumbs.db
22
.DS_Store
3+
.claude
34
.gradle
45
.cache
56
.nextflow*
@@ -26,6 +27,7 @@ wave.log
2627
build-workspace/
2728
scan-workspace/
2829
/k8s/dev/config-k3d.yml
30+
/.wave-test
2931

3032
# Docs
3133
.vercel

.specify/memory/constitution.md

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
<!--
2+
Sync Impact Report:
3+
- Version change: [unversioned template] → 1.0.0
4+
- Modified principles: All (initialized from template)
5+
- Added sections: All core principles and governance sections
6+
- Removed sections: None
7+
- Templates requiring updates:
8+
✅ plan-template.md - Reviewed, Constitution Check section aligns
9+
✅ spec-template.md - Reviewed, requirement structure aligns
10+
✅ tasks-template.md - Reviewed, task organization aligns
11+
✅ checklist-template.md - Reviewed, compatible with principles
12+
- Follow-up TODOs: None
13+
-->
14+
15+
# Wave Containers Constitution
16+
17+
## Core Principles
18+
19+
### I. Service-Oriented Architecture
20+
21+
Wave MUST maintain a clear separation of concerns through distinct service boundaries. Each service (ContainerBuildService,
22+
ContainerMirrorService, ContainerScanService, RegistryProxyService, BlobCacheService) MUST be independently testable and
23+
have a single, well-defined responsibility. Controllers MUST remain thin, delegating business logic to services.
24+
25+
**Rationale**: Microservices architecture enables independent scaling, testing, and maintenance of distinct container
26+
provisioning capabilities. Clear boundaries prevent coupling and facilitate parallel development.
27+
28+
### II. Container Platform Agnosticism
29+
30+
Wave MUST support multiple container platforms (Docker, Kubernetes, Singularity) and registries (Docker Hub, Quay.io,
31+
AWS ECR, Azure CR) without hardcoding platform-specific assumptions into core logic. Platform-specific strategies
32+
MUST be isolated behind abstract interfaces.
33+
34+
**Rationale**: Container ecosystem diversity requires flexible provisioning that adapts to client infrastructure without
35+
forcing migration or lock-in.
36+
37+
### III. Ephemeral-First Design
38+
39+
All container operations MUST assume ephemeral lifecycle by default. Containers, build contexts, and intermediate
40+
artifacts MUST be automatically garbage-collected. Long-term persistence MUST be explicit opt-in through user-provided
41+
registry credentials and push operations.
42+
43+
**Rationale**: Wave's core value is on-demand provisioning without manual registry management. Ephemeral-first design
44+
prevents storage bloat and reduces operational overhead.
45+
46+
### IV. Proxy Transparency
47+
48+
When acting as a registry proxy, Wave MUST remain transparent to Docker clients and comply strictly with the Docker
49+
Registry v2 API specification. Manifest instrumentation and layer injection MUST appear seamless to standard container
50+
tooling.
51+
52+
**Rationale**: Compatibility with existing container toolchains (docker pull, kubectl, etc.) is non-negotiable for adoption.
53+
Protocol compliance prevents breaking changes in client workflows.
54+
55+
### V. Async-by-Default Operations
56+
57+
All I/O-bound operations (registry pulls, builds, scans, blob storage) MUST use Micronaut Reactor non-blocking patterns.
58+
Blocking calls are prohibited in HTTP request handlers. Long-running operations MUST use JobManager for background processing.
59+
60+
**Rationale**: Container operations involve large data transfers and external API calls. Blocking threads under load
61+
causes cascading failures. Reactive patterns ensure resource efficiency and throughput under concurrency.
62+
63+
### VI. Security Scanning Integration
64+
65+
Container security scanning MUST be an opt-in, asynchronous operation that never blocks image provisioning. Scan results
66+
MUST be persisted independently and queryable after container delivery. Scanning failures MUST NOT prevent container access.
67+
68+
**Rationale**: Security scanning adds latency. Making it non-blocking preserves Wave's primary value (fast provisioning)
69+
while enabling security workflows for teams that require them.
70+
71+
### VII. Multi-Platform Build Support
72+
73+
Container builds MUST support cross-platform compilation (linux/amd64, linux/arm64) without requiring users to manage
74+
build infrastructure. Platform selection MUST be declarative via API parameters. Build strategy selection (Docker vs Kubernetes)
75+
MUST be transparent to users.
76+
77+
**Rationale**: ARM64 adoption in cloud and edge requires transparent multi-platform support. Kubernetes-based builds
78+
provide scalability and isolation that local Docker daemon cannot.
79+
80+
## Storage & Persistence Requirements
81+
82+
### Data Layer Principles
83+
84+
- PostgreSQL MUST be used for structured metadata (build records, scan results, job state)
85+
- Redis MUST be used for ephemeral caching and rate-limiting state
86+
- Object storage (S3-compatible) MUST be used for blobs, layers, and build contexts
87+
- Database migrations MUST be versioned and reversible
88+
- No business logic in SQL; use application-layer queries via Micronaut Data JDBC
89+
90+
**Rationale**: Clear storage tier separation prevents cross-cutting concerns. Postgres handles ACID requirements, Redis
91+
handles high-frequency ephemeral state, S3 handles blob scale.
92+
93+
### Authentication & Authorization
94+
95+
- Registry credentials MUST be encrypted at rest
96+
- JWT tokens MUST be used for Tower integration authentication
97+
- Rate limiting MUST be enforced per-user via Spillway library
98+
- Service-to-service calls within Kubernetes MUST use pod identity where available
99+
100+
**Rationale**: Wave handles sensitive registry credentials and must prevent credential leakage. Rate limiting prevents
101+
abuse of compute-intensive build operations.
102+
103+
## Testing & Quality Standards
104+
105+
### Testing Requirements
106+
107+
- All services MUST have unit tests using Spock 2 framework
108+
- Integration tests MUST use Testcontainers for external dependencies (Postgres, Redis)
109+
- Controller tests MUST mock service layer dependencies
110+
- Test coverage MUST be measured via JaCoCo and reported after test runs
111+
- Tests MUST NOT depend on external registries; use local registry containers or mocks
112+
113+
**Rationale**: Groovy + Spock provide expressive BDD-style tests. Testcontainers ensure consistent CI/CD environments.
114+
External registry dependencies cause flaky tests and rate-limiting issues.
115+
116+
### Performance Standards
117+
118+
- HTTP endpoints MUST respond within 200ms p95 for proxy operations (excluding upstream registry latency)
119+
- Build operations MUST queue within 100ms and report job ID
120+
- Blob cache MUST serve layers with 90%+ hit rate under normal load
121+
- Memory usage MUST remain under 2GB heap for typical workloads
122+
123+
**Rationale**: Wave sits in the critical path for container pulls. Latency directly impacts developer and CI/CD workflows.
124+
Performance budgets prevent regressions.
125+
126+
## Governance
127+
128+
### Amendment Process
129+
130+
Constitution changes MUST be documented in Git commit messages with rationale. MAJOR changes (removing principles,
131+
incompatible policy shifts) require version bump to next major. MINOR changes (new principles, expanded guidance) require
132+
minor version bump. PATCH changes (clarifications, wording) require patch version bump.
133+
134+
### Compliance Review
135+
136+
All pull requests MUST be reviewed against constitution principles. Violations MUST be explicitly justified with
137+
"Why Needed" and "Simpler Alternative Rejected" documentation in design docs. Unjustified complexity MUST be rejected.
138+
139+
### Versioning Policy
140+
141+
Wave follows semantic versioning (MAJOR.MINOR.PATCH):
142+
- MAJOR: Breaking API changes, incompatible registry protocol changes
143+
- MINOR: New features (new registry support, new build capabilities)
144+
- PATCH: Bug fixes, performance improvements, security patches
145+
146+
Release process:
147+
1. Update VERSION file
148+
2. Update changelog.txt with changes since last release
149+
3. Commit with `[release]` tag in first line of commit message
150+
4. Push to upstream master branch
151+
152+
**Rationale**: Semantic versioning provides clear upgrade expectations. Tagged release commits enable automated CI/CD
153+
release workflows.
154+
155+
**Version**: 1.0.0 | **Ratified**: 2025-10-28 | **Last Amended**: 2025-10-28
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
#!/usr/bin/env bash
2+
3+
# Consolidated prerequisite checking script
4+
#
5+
# This script provides unified prerequisite checking for Spec-Driven Development workflow.
6+
# It replaces the functionality previously spread across multiple scripts.
7+
#
8+
# Usage: ./check-prerequisites.sh [OPTIONS]
9+
#
10+
# OPTIONS:
11+
# --json Output in JSON format
12+
# --require-tasks Require tasks.md to exist (for implementation phase)
13+
# --include-tasks Include tasks.md in AVAILABLE_DOCS list
14+
# --paths-only Only output path variables (no validation)
15+
# --help, -h Show help message
16+
#
17+
# OUTPUTS:
18+
# JSON mode: {"FEATURE_DIR":"...", "AVAILABLE_DOCS":["..."]}
19+
# Text mode: FEATURE_DIR:... \n AVAILABLE_DOCS: \n ✓/✗ file.md
20+
# Paths only: REPO_ROOT: ... \n BRANCH: ... \n FEATURE_DIR: ... etc.
21+
22+
set -e
23+
24+
# Parse command line arguments
25+
JSON_MODE=false
26+
REQUIRE_TASKS=false
27+
INCLUDE_TASKS=false
28+
PATHS_ONLY=false
29+
30+
for arg in "$@"; do
31+
case "$arg" in
32+
--json)
33+
JSON_MODE=true
34+
;;
35+
--require-tasks)
36+
REQUIRE_TASKS=true
37+
;;
38+
--include-tasks)
39+
INCLUDE_TASKS=true
40+
;;
41+
--paths-only)
42+
PATHS_ONLY=true
43+
;;
44+
--help|-h)
45+
cat << 'EOF'
46+
Usage: check-prerequisites.sh [OPTIONS]
47+
48+
Consolidated prerequisite checking for Spec-Driven Development workflow.
49+
50+
OPTIONS:
51+
--json Output in JSON format
52+
--require-tasks Require tasks.md to exist (for implementation phase)
53+
--include-tasks Include tasks.md in AVAILABLE_DOCS list
54+
--paths-only Only output path variables (no prerequisite validation)
55+
--help, -h Show this help message
56+
57+
EXAMPLES:
58+
# Check task prerequisites (plan.md required)
59+
./check-prerequisites.sh --json
60+
61+
# Check implementation prerequisites (plan.md + tasks.md required)
62+
./check-prerequisites.sh --json --require-tasks --include-tasks
63+
64+
# Get feature paths only (no validation)
65+
./check-prerequisites.sh --paths-only
66+
67+
EOF
68+
exit 0
69+
;;
70+
*)
71+
echo "ERROR: Unknown option '$arg'. Use --help for usage information." >&2
72+
exit 1
73+
;;
74+
esac
75+
done
76+
77+
# Source common functions
78+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
79+
source "$SCRIPT_DIR/common.sh"
80+
81+
# Get feature paths and validate branch
82+
eval $(get_feature_paths)
83+
check_feature_branch "$CURRENT_BRANCH" "$HAS_GIT" || exit 1
84+
85+
# If paths-only mode, output paths and exit (support JSON + paths-only combined)
86+
if $PATHS_ONLY; then
87+
if $JSON_MODE; then
88+
# Minimal JSON paths payload (no validation performed)
89+
printf '{"REPO_ROOT":"%s","BRANCH":"%s","FEATURE_DIR":"%s","FEATURE_SPEC":"%s","IMPL_PLAN":"%s","TASKS":"%s"}\n' \
90+
"$REPO_ROOT" "$CURRENT_BRANCH" "$FEATURE_DIR" "$FEATURE_SPEC" "$IMPL_PLAN" "$TASKS"
91+
else
92+
echo "REPO_ROOT: $REPO_ROOT"
93+
echo "BRANCH: $CURRENT_BRANCH"
94+
echo "FEATURE_DIR: $FEATURE_DIR"
95+
echo "FEATURE_SPEC: $FEATURE_SPEC"
96+
echo "IMPL_PLAN: $IMPL_PLAN"
97+
echo "TASKS: $TASKS"
98+
fi
99+
exit 0
100+
fi
101+
102+
# Validate required directories and files
103+
if [[ ! -d "$FEATURE_DIR" ]]; then
104+
echo "ERROR: Feature directory not found: $FEATURE_DIR" >&2
105+
echo "Run /speckit.specify first to create the feature structure." >&2
106+
exit 1
107+
fi
108+
109+
if [[ ! -f "$IMPL_PLAN" ]]; then
110+
echo "ERROR: plan.md not found in $FEATURE_DIR" >&2
111+
echo "Run /speckit.plan first to create the implementation plan." >&2
112+
exit 1
113+
fi
114+
115+
# Check for tasks.md if required
116+
if $REQUIRE_TASKS && [[ ! -f "$TASKS" ]]; then
117+
echo "ERROR: tasks.md not found in $FEATURE_DIR" >&2
118+
echo "Run /speckit.tasks first to create the task list." >&2
119+
exit 1
120+
fi
121+
122+
# Build list of available documents
123+
docs=()
124+
125+
# Always check these optional docs
126+
[[ -f "$RESEARCH" ]] && docs+=("research.md")
127+
[[ -f "$DATA_MODEL" ]] && docs+=("data-model.md")
128+
129+
# Check contracts directory (only if it exists and has files)
130+
if [[ -d "$CONTRACTS_DIR" ]] && [[ -n "$(ls -A "$CONTRACTS_DIR" 2>/dev/null)" ]]; then
131+
docs+=("contracts/")
132+
fi
133+
134+
[[ -f "$QUICKSTART" ]] && docs+=("quickstart.md")
135+
136+
# Include tasks.md if requested and it exists
137+
if $INCLUDE_TASKS && [[ -f "$TASKS" ]]; then
138+
docs+=("tasks.md")
139+
fi
140+
141+
# Output results
142+
if $JSON_MODE; then
143+
# Build JSON array of documents
144+
if [[ ${#docs[@]} -eq 0 ]]; then
145+
json_docs="[]"
146+
else
147+
json_docs=$(printf '"%s",' "${docs[@]}")
148+
json_docs="[${json_docs%,}]"
149+
fi
150+
151+
printf '{"FEATURE_DIR":"%s","AVAILABLE_DOCS":%s}\n' "$FEATURE_DIR" "$json_docs"
152+
else
153+
# Text output
154+
echo "FEATURE_DIR:$FEATURE_DIR"
155+
echo "AVAILABLE_DOCS:"
156+
157+
# Show status of each potential document
158+
check_file "$RESEARCH" "research.md"
159+
check_file "$DATA_MODEL" "data-model.md"
160+
check_dir "$CONTRACTS_DIR" "contracts/"
161+
check_file "$QUICKSTART" "quickstart.md"
162+
163+
if $INCLUDE_TASKS; then
164+
check_file "$TASKS" "tasks.md"
165+
fi
166+
fi

0 commit comments

Comments
 (0)