Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 120 additions & 0 deletions .github/workflows/release-gate.yml
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 \

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Make the Clang warnings-as-errors gate buildable

With the Ubuntu/Clang configuration used by this job, enabling CPP_REQUEST_WARNINGS_AS_ERRORS makes the new gate fail during compilation before any sanitizer tests run: Clang reports -Wsign-conversion for the character loops in src/core/url.cpp:42 and src/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 👍 / 👎.

-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
137 changes: 137 additions & 0 deletions docs/release/v1.0-acceptance.md
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.
Loading
Loading