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
76 changes: 76 additions & 0 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
---
Language: Cpp
BasedOnStyle: LLVM
IndentWidth: 4
TabWidth: 4
UseTab: Always
ColumnLimit: 100
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Left
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: true
BinPackParameters: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeColon
BreakStringLiterals: true
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
FixNamespaceComments: true
IncludeBlocks: Regroup
IncludeCategories:
- Regex: '^"spc/'
Priority: 1
- Regex: '^<'
Priority: 2
- Regex: '.*'
Priority: 3
IndentCaseLabels: true
IndentPPDirectives: None
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: false
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Left
ReflowComments: true
SortIncludes: true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInCStyleCastParentheses: false
SpacesInContainerLiterals: true
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: c++20
34 changes: 34 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# EditorConfig — consistent style across editors for PredictionCastAI C++ repos
# https://editorconfig.org/
# Matches the fleet-standard .clang-format: tab-indent (width 4), LF, UTF-8.

root = true

[*]
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.{cpp,hpp,c,h,cc,cxx,hxx}]
indent_style = tab
indent_size = 4
max_line_length = 100

[*.{cmake,CMakeLists.txt}]
indent_style = tab
indent_size = 4

[Makefile]
indent_style = tab

[*.{yml,yaml}]
indent_style = space
indent_size = 2

[*.{json,jsonc}]
indent_style = space
indent_size = 2

[*.md]
trim_trailing_whitespace = false
38 changes: 38 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Bug report
description: A bug, crash, or incorrect behavior.
labels: [bug]
body:
- type: textarea
id: what
attributes:
label: What happened?
description: A clear description of the bug. Include error messages, crash backtraces, or wire-format dumps if relevant.
validations:
required: true
- type: textarea
id: repro
attributes:
label: Reproduction steps
description: Minimum steps + minimum code that triggers the bug. Inline snippets are fine; please don't paste a whole project.
placeholder: |
1. Build with `make build`
2. Run `./build/bin/example_<name>`
3. Observe ...
validations:
required: true
- type: textarea
id: env
attributes:
label: Environment
description: SDK version, compiler, OS, dependency versions (libcurl/libwebsockets/openssl).
placeholder: |
- SDK version: vX.Y.Z (or commit SHA)
- OS: Ubuntu 24.04 / macOS 14 / Windows 2022
- Compiler: gcc 13.3 / clang 18 / MSVC 19.40
- cmake --version: ...
validations:
required: true
- type: markdown
attributes:
value: |
**Security vulnerabilities:** please use the channel in [SECURITY.md](../SECURITY.md), not a public issue.
5 changes: 5 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: Security vulnerability
url: https://github.com/Reddimus/spc-cpp/security/policy
about: Please do NOT open a public issue for security vulnerabilities. Use the private channel in SECURITY.md.
21 changes: 21 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: Feature request
description: Propose a new API surface, endpoint coverage gap, or developer-experience improvement.
labels: [enhancement]
body:
- type: textarea
id: what
attributes:
label: What feature would you like?
description: Describe the API or behavior you'd like to see, and what consumer code it would enable.
validations:
required: true
- type: textarea
id: alternatives
attributes:
label: Alternatives considered
description: Other ways you could solve this today (workarounds, system installs, vendored copies). Helps us see whether the request is a gap or a preference.
- type: textarea
id: context
attributes:
label: Additional context
description: Links to upstream API docs, related issues, or example code.
16 changes: 16 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
## Summary

<!-- 1-3 sentences. What changed and why. Link the upstream issue if any. -->

## Test plan

<!-- Bullet list of how you verified the change. Include commands you ran. -->

- [ ] `make lint` clean
- [ ] `make test` passes (or specify which subset)
- [ ] CHANGELOG.md updated under `## [Unreleased]` (if user-visible)
- [ ] No new public API → no SemVer minor/major bump needed

## Notes for reviewers

<!-- Optional: anything subtle about the change, alternatives considered, follow-ups. -->
54 changes: 54 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
name: CI

on:
push:
branches: [main]
pull_request:
workflow_dispatch:

jobs:
build-linux:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6

- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
build-essential cmake pkg-config clang-format \
libcurl4-openssl-dev

- name: Build
run: make build

- name: Test
run: make test

- name: Lint
run: make lint

build-macos:
runs-on: macos-latest
steps:
- uses: actions/checkout@v6

- name: Install dependencies
run: |
brew install pkg-config curl clang-format
echo "CMAKE_PREFIX_PATH=$(brew --prefix curl)" >> "$GITHUB_ENV"

- name: Build
run: make build

- name: Test
run: make test

- name: Lint
run: make lint

markdown-lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: DavidAnson/markdownlint-cli2-action@v23
72 changes: 72 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
name: Release

# Auto-publish a GitHub Release when a vX.Y.Z tag is pushed.
# Body is the matching section of CHANGELOG.md (between the "## [X.Y.Z]"
# heading and the next "## " heading), so tag → release stays in sync
# without a separate manual step.

on:
push:
tags:
- "v[0-9]+.[0-9]+.[0-9]+"
- "v[0-9]+.[0-9]+.[0-9]+-*"

permissions:
contents: write

jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0

- name: Verify tag matches CMakeLists project VERSION
# Pin the source-of-truth: the tag X.Y.Z must equal the
# `project(spc-cpp VERSION X.Y.Z ...)` field in
# CMakeLists.txt. Without this guard the two can drift
# silently and corrupt `find_package(spc-cpp VERSION X.Y.Z)`
# consumer queries (the generated spc-cppConfigVersion.cmake
# tracks PROJECT_VERSION).
run: |
tag="${GITHUB_REF#refs/tags/}"
version="${tag#v}"
cmake_version=$(awk -F 'VERSION |LANGUAGES' '
/^project\(spc-cpp / { gsub(/[ \t]/,"",$2); print $2; exit }
' CMakeLists.txt)
if [ "$cmake_version" != "$version" ]; then
echo "::error::tag $tag implies version '$version' but CMakeLists.txt says '$cmake_version'" >&2
echo "Bump 'project(spc-cpp VERSION ...)' to match before tagging." >&2
exit 1
fi
echo "OK: tag $tag matches CMakeLists VERSION $cmake_version"

- name: Extract release notes from CHANGELOG.md
run: |
tag="${GITHUB_REF#refs/tags/}"
version="${tag#v}"
# Pipe directly to a file. DO NOT capture into a shell var
# and echo it back — bash treats backticks as command
# substitution, which silently strips every inline `code`
# span from the release body. Reading via `gh release create
# --notes-file` preserves the bytes verbatim.
awk -v v="$version" '
$0 ~ "^## \\["v"\\]" { capture=1; next }
capture && /^## / { exit }
capture { print }
' CHANGELOG.md > /tmp/release_notes.md
if [ ! -s /tmp/release_notes.md ]; then
printf 'Release %s. See CHANGELOG.md for details.\n' "$tag" \
> /tmp/release_notes.md
fi

- name: Create GitHub Release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
tag="${GITHUB_REF#refs/tags/}"
gh release create "$tag" \
--title "$tag" \
--notes-file /tmp/release_notes.md \
--verify-tag
54 changes: 54 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
build/
build-*/
cmake-build-*/
.cache/
compile_commands.json

# IDE
.vscode/
.idea/
*.swp
*.swo
*~

# OS
.DS_Store
Thumbs.db

# Env
.env
*.pem

# === Production-hardening patterns (added 2026-05-02) ===
# Credentials — never commit secrets to a public SDK
*.pem
*.key
*.p12
*.pfx
credentials.json
credentials*.json
secrets/
service-account*.json
gha-secrets.txt

# Build cache
_deps/
build-*/

# Coverage + analysis artifacts
*.gcov
*.gcda
*.gcno
coverage/
*.profraw
*.profdata

# Sanitizer / valgrind output
asan.log
ubsan.log
*.callgrind
*.cachegrind

# OS noise
.DS_Store
Thumbs.db
Loading
Loading