-
Notifications
You must be signed in to change notification settings - Fork 0
release: add v1.0 acceptance gates #30
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
aade9ca
ci: add v1 release gate
zuudevs 3926853
test: compile public headers in isolation
zuudevs 33fcf2d
test: cover installed public header surface
zuudevs c9f45fe
docs: add v1 acceptance matrix
zuudevs eb346a0
docs: fix JSON example literals
zuudevs 6c03c9c
docs: enter v1 release hardening
zuudevs 3d1cb04
fix: make URL byte conversion explicit
zuudevs ed24c00
fix: make HTTP byte conversions explicit
zuudevs 004f0a9
fix: make response byte validation explicit
zuudevs 93c2f06
fix: make chunked validation byte conversions explicit
zuudevs File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,120 @@ | ||
| name: v1 Release Gate | ||
|
|
||
| on: | ||
| workflow_dispatch: | ||
| push: | ||
| branches: [ main, master ] | ||
| paths: | ||
| - 'include/**' | ||
| - 'src/**' | ||
| - 'tests/**' | ||
| - 'examples/**' | ||
| - 'cmake/**' | ||
| - 'CMakeLists.txt' | ||
| - 'vcpkg.json' | ||
| - 'vcpkg-configuration.json' | ||
| - '.github/workflows/release-gate.yml' | ||
| pull_request: | ||
| branches: [ main, master ] | ||
| paths: | ||
| - 'include/**' | ||
| - 'src/**' | ||
| - 'tests/**' | ||
| - 'examples/**' | ||
| - 'cmake/**' | ||
| - 'CMakeLists.txt' | ||
| - 'vcpkg.json' | ||
| - 'vcpkg-configuration.json' | ||
| - '.github/workflows/release-gate.yml' | ||
|
|
||
| jobs: | ||
| sanitizers: | ||
| name: ASan + UBSan (Clang, C++17) | ||
| runs-on: ubuntu-latest | ||
| env: | ||
| ASAN_OPTIONS: detect_leaks=1:halt_on_error=1 | ||
| UBSAN_OPTIONS: halt_on_error=1:print_stacktrace=1 | ||
|
|
||
| steps: | ||
| - name: Checkout Repository | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Configure Sanitizer Build | ||
| shell: bash | ||
| run: | | ||
| cmake -B build-sanitize \ | ||
| -DCMAKE_BUILD_TYPE=Debug \ | ||
| -DCMAKE_CXX_COMPILER=clang++ \ | ||
| -DCPP_REQUEST_ENABLE_SANITIZERS=ON \ | ||
| -DCPP_REQUEST_WARNINGS_AS_ERRORS=ON \ | ||
| -DCPP_REQUEST_BUILD_BENCHMARKS=OFF \ | ||
| -DCPP_REQUEST_BUILD_EXAMPLES=ON | ||
|
|
||
| - name: Build Sanitizer Configuration | ||
| shell: bash | ||
| run: | | ||
| cmake --build build-sanitize --config Debug | ||
|
|
||
| - name: Run Sanitized Tests | ||
| shell: bash | ||
| run: | | ||
| ctest \ | ||
| --test-dir build-sanitize \ | ||
| --build-config Debug \ | ||
| --output-on-failure \ | ||
| -E '^PackageConsumer\.InstallAndUse$' | ||
|
|
||
| cxx20-consumer: | ||
| name: C++20 Compatibility + Installed Consumer | ||
| runs-on: ubuntu-latest | ||
|
|
||
| steps: | ||
| - name: Checkout Repository | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Configure C++20 Build | ||
| shell: bash | ||
| run: | | ||
| cmake -B build-cxx20 \ | ||
| -DCMAKE_BUILD_TYPE=Release \ | ||
| -DCMAKE_CXX_STANDARD=20 \ | ||
| -DCMAKE_CXX_STANDARD_REQUIRED=ON \ | ||
| -DCPP_REQUEST_WARNINGS_AS_ERRORS=ON \ | ||
| -DCPP_REQUEST_BUILD_BENCHMARKS=OFF \ | ||
| -DCPP_REQUEST_BUILD_EXAMPLES=ON | ||
|
|
||
| - name: Build and Test C++20 Configuration | ||
| shell: bash | ||
| run: | | ||
| cmake --build build-cxx20 --config Release | ||
| ctest \ | ||
| --test-dir build-cxx20 \ | ||
| --build-config Release \ | ||
| --output-on-failure | ||
|
|
||
| - name: Install Package | ||
| shell: bash | ||
| run: | | ||
| cmake --install build-cxx20 \ | ||
| --config Release \ | ||
| --prefix "$PWD/stage" | ||
|
|
||
| - name: Configure Installed C++20 Consumer | ||
| shell: bash | ||
| run: | | ||
| cmake \ | ||
| -S tests/package_consumer \ | ||
| -B build-consumer-cxx20 \ | ||
| -DCMAKE_BUILD_TYPE=Release \ | ||
| -DCMAKE_PREFIX_PATH="$PWD/stage" \ | ||
| -DCMAKE_CXX_STANDARD=20 \ | ||
| -DCMAKE_CXX_STANDARD_REQUIRED=ON | ||
|
|
||
| - name: Build and Run Installed C++20 Consumer | ||
| shell: bash | ||
| run: | | ||
| cmake --build build-consumer-cxx20 --config Release | ||
| ctest \ | ||
| --test-dir build-consumer-cxx20 \ | ||
| --build-config Release \ | ||
| --output-on-failure | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,137 @@ | ||
| # v1.0 Acceptance Matrix | ||
|
|
||
| ## Status | ||
|
|
||
| - Project: `cpp_request` | ||
| - Target: v1.0 release candidate | ||
| - Current project version during hardening: v0.9.0 | ||
| - Scope: synchronous HTTP/1.1 over plaintext TCP | ||
| - Purpose: map frozen v1 requirements to concrete implementation/test/CI evidence | ||
|
|
||
| This document is a release gate, not a replacement for `docs/requirements/functional.md` or `docs/requirements/non-functional.md`. A requirement remains authoritative in those frozen documents. This matrix records how the repository verifies it before the version is promoted to v1.0.0. | ||
|
|
||
| A v1.0 version bump/tag must not happen until all required CI checks are green and no release-blocking correctness issue remains. | ||
|
|
||
| --- | ||
|
|
||
| ## Functional requirement coverage | ||
|
|
||
| | Requirement area | Requirement IDs | Primary evidence | Gate status | | ||
| | --- | --- | --- | --- | | ||
| | HTTP/1.1 + methods | REQ-HTTP-001, REQ-HTTP-002 | `request_serializer_test.cpp`, `client_test.cpp` | Covered | | ||
| | Custom headers + query | REQ-HTTP-003, REQ-HTTP-004 | `headers_test.cpp`, `request_test.cpp`, `query_test.cpp` | Covered | | ||
| | In-memory request body | REQ-HTTP-005 | `request_serializer_test.cpp`, `client_test.cpp` | Covered | | ||
| | URL / HTTP-only scheme | REQ-URL-001, REQ-URL-002 | `url_test.cpp`, `client_test.cpp` | Covered | | ||
| | DNS / IPv4 / IPv6 / native sockets | REQ-NET-001..004 | `resolver_test.cpp`, `native_socket_test.cpp`, `tcp_connection_test.cpp` | Covered | | ||
| | TCP establishment + reuse + close semantics | REQ-CONN-001..003 | `tcp_connection_test.cpp`, `client_reuse_test.cpp`, response-parser reuse tests | Covered | | ||
| | RAII socket ownership | REQ-CONN-004 | `native_socket_test.cpp`, timeout/failure-path connection tests | Covered | | ||
| | Status line + headers | REQ-RESP-001, REQ-RESP-002 | `response_parser_test.cpp` | Covered | | ||
| | Content-Length + chunked + in-memory response | REQ-RESP-003..005 | `response_parser_test.cpp`, `chunked_decoder_test.cpp`, `response_limits_test.cpp` | Covered | | ||
| | HEAD semantics | REQ-RESP-006 | `response_parser_test.cpp`, client loopback tests | Covered | | ||
| | Redirects | REQ-REDIR-001..003 | `redirect_test.cpp`, `client_redirect_test.cpp` | Covered | | ||
| | Connect timeout | REQ-TIME-001 | `tcp_connection_test.cpp` (`ConnectTimeout`) | Covered | | ||
| | Read timeout | REQ-TIME-002 | `tcp_io_test.cpp` (`ReadTimeoutClosesConnection`) | Covered | | ||
| | Write timeout | REQ-TIME-003 | `tcp_io_test.cpp` (`WriteTimeoutClosesConnection`) | Covered | | ||
| | Structured Result / errors | REQ-ERR-001..003 | `result_test.cpp`, protocol/transport error tests, `docs/api/error-model.md` | Covered | | ||
| | Stateful client + convenience helpers | REQ-API-001, REQ-API-002 | `client_test.cpp`, public examples | Covered | | ||
| | Native socket encapsulation | REQ-API-003 | public-header isolation target + installed consumer | Release gate | | ||
| | No mandatory PImpl | REQ-API-004 | public type definitions / implementation inspection | Covered | | ||
| | Thread-safety contract | REQ-API-005 | `README.md`, `docs/getting-started.md`, `docs/api/public-api.md` | Covered | | ||
| | `std::string_view` contract | REQ-API-006 | public headers + `docs/api/lifetime.md` | Covered | | ||
|
|
||
| --- | ||
|
|
||
| ## Non-functional requirement coverage | ||
|
|
||
| | Requirement area | Requirement IDs | Primary evidence | Gate status | | ||
| | --- | --- | --- | --- | | ||
| | C++17 minimum | REQ-COMP-001 | target `cxx_std_17`, normal CI matrix | Covered | | ||
| | Newer-standard compatibility | REQ-COMP-002 | v1 release gate C++20 build + installed consumer | Release gate | | ||
| | Zero third-party runtime dependency | REQ-DEP-001 | native socket implementation, install-tree consumer | Covered | | ||
| | Dev dependencies do not leak | REQ-DEP-002, REQ-BUILD-003 | package export + `PackageConsumer.InstallAndUse` | Covered | | ||
| | Allocation/copy discipline | REQ-PERF-001, REQ-PERF-002 | borrowed request body boundary, parser design, benchmarkable hot paths | Reviewed | | ||
| | No unnecessary virtual indirection | REQ-PERF-003 | architecture/source inspection | Reviewed | | ||
| | Connection reuse | REQ-PERF-004 | `client_reuse_test.cpp`, reuse-vs-reconnect benchmark | Covered | | ||
| | Benchmarkable hot paths | REQ-PERF-005 | benchmark suite + Benchmark Smoke workflow | Covered | | ||
| | Windows / Linux | REQ-PORT-001, REQ-PORT-002 | Debug/Release CI jobs | Covered | | ||
| | macOS compatibility | REQ-PORT-003 | Debug/Release CI jobs | Covered | | ||
| | Platform isolation | REQ-PORT-004 | `src/platform`, `src/net`, `src/http` boundaries + public-header gate | Covered | | ||
| | Deterministic cleanup | REQ-REL-001 | RAII tests + sanitizer gate + timeout-close tests | Release gate | | ||
| | Predictable errors / no downgrade | REQ-REL-002, REQ-REL-003 | result/error tests, HTTPS rejection tests | Covered | | ||
| | Bounded waits | REQ-REL-004 | connect/read/write timeout tests | Covered | | ||
| | Small public surface | REQ-APIQ-001 | eight installed public headers + public-header isolation gate | Release gate | | ||
| | Value-oriented types | REQ-APIQ-002 | public type inspection | Reviewed | | ||
| | Move support | REQ-APIQ-003 | client move tests / resource ownership tests | Covered | | ||
| | Thread-safety docs | REQ-APIQ-004 | README / getting-started / public API docs | Covered | | ||
| | CMake build entry point | REQ-BUILD-001 | root CMake + modular build options | Covered | | ||
| | Installable package | REQ-BUILD-002 | install/export config + installed consumer | Covered | | ||
| | Unit tests | REQ-TEST-001 | protocol/URL/header/chunk/parser tests | Covered | | ||
| | Integration tests | REQ-TEST-002 | local loopback client/reuse/redirect/timeout tests | Covered | | ||
| | No public HTTP service in required tests | REQ-TEST-003 | loopback-controlled networking tests | Covered | | ||
| | Cross-platform CI | REQ-TEST-004 | Windows/Linux/macOS matrix | Covered | | ||
| | Public API documentation | REQ-DOC-001 | README, getting-started, `docs/api/*` | Covered | | ||
| | Scope documentation | REQ-DOC-002 | README + frozen requirements | Covered | | ||
| | Architecture documentation | REQ-DOC-003 | `docs/architecture/*` | Covered | | ||
|
|
||
| --- | ||
|
|
||
| ## Automated v1 release gates | ||
|
|
||
| ### Existing gates | ||
|
|
||
| 1. `C++ CI Build` | ||
| - Windows, Linux, macOS. | ||
| - Debug and Release. | ||
| - unit + loopback integration tests. | ||
| - install-tree consumer test. | ||
| - examples compile as part of the top-level build. | ||
|
|
||
| 2. `Benchmark Smoke` | ||
| - Windows, Linux, macOS Release builds. | ||
| - all v0.9 benchmark executables build and execute locally. | ||
|
|
||
| ### Added by release hardening | ||
|
|
||
| 3. `v1 Release Gate / ASan + UBSan (Clang, C++17)` | ||
| - Debug Clang build. | ||
| - warnings as errors. | ||
| - AddressSanitizer + UndefinedBehaviorSanitizer. | ||
| - leak detection enabled on Linux. | ||
| - unit and loopback tests run under sanitizers. | ||
| - the install-consumer test is excluded from this sanitizer run because an independently configured consumer would otherwise need matching sanitizer link flags. | ||
|
|
||
| 4. `v1 Release Gate / C++20 Compatibility + Installed Consumer` | ||
| - full C++20 project build and tests. | ||
| - warnings as errors. | ||
| - installs the package to a staging prefix. | ||
| - separately configures, builds, and runs the installed consumer as C++20. | ||
|
|
||
| 5. Public-header isolation compile target | ||
| - each public header is compiled in its own translation unit. | ||
| - only `${PROJECT_SOURCE_DIR}/include` is available. | ||
| - no `src/` include path is supplied. | ||
| - catches missing direct includes and accidental internal/platform dependencies. | ||
|
|
||
| --- | ||
|
|
||
| ## Manual release review | ||
|
|
||
| The following checks remain deliberate human review items before the final v1.0.0 bump/tag: | ||
|
|
||
| - confirm no unresolved correctness issue can corrupt HTTP framing or connection reuse, | ||
| - review performance claims against the committed benchmark suite rather than intuition, | ||
| - review public API/lifetime docs against current headers, | ||
| - confirm the installed target has no GTest/Google Benchmark dependency, | ||
| - confirm no post-v1 feature slipped into the frozen scope, | ||
| - review release notes/versioning/tagging metadata. | ||
|
|
||
| --- | ||
|
|
||
| ## Promotion rule | ||
|
|
||
| When all automated release-gate checks are green and the manual review above has no blocker, the next change should be a focused release PR that: | ||
|
|
||
| 1. changes the project version from `0.9.0` to `1.0.0`, | ||
| 2. updates roadmap/release status to v1.0 complete, | ||
| 3. adds final release notes/changelog metadata if desired, | ||
| 4. creates the v1.0 tag/release only after that release PR is merged. |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With the Ubuntu/Clang configuration used by this job, enabling
CPP_REQUEST_WARNINGS_AS_ERRORSmakes the new gate fail during compilation before any sanitizer tests run: Clang reports-Wsign-conversionfor the character loops insrc/core/url.cpp:42andsrc/http/request_serializer.cpp:93,134,143. I reproduced this using the workflow's configuration with Clang 17; fix these warnings or avoid promoting them to errors here so the required release gate can become green.Useful? React with 👍 / 👎.