Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
93f2856
chore: Update release configuration and add GitHub Actions workflows …
disafronov Dec 5, 2025
34f9ec6
ci: Correct regex for release candidate tags in GitHub Actions workflow
disafronov Dec 5, 2025
c632d83
chore: Refine release configuration for semantic release
disafronov Dec 5, 2025
1ddedd6
chore: Add version verification step in GitHub Actions workflows
disafronov Dec 5, 2025
42a45bd
chore: Remove workflow_dispatch from GitHub Actions for publishing
disafronov Dec 5, 2025
dd295ea
chore: Simplify release branch configuration in .releaserc.json
disafronov Dec 5, 2025
397f73b
refactor: Enhance schema validation and nested value handling
disafronov Dec 5, 2025
790cb09
chore(release): 0.1.1-rc.1 [skip ci]
semantic-release-bot Dec 5, 2025
3fc25e9
ci: Correct quote style for regex pattern in publish.yaml
disafronov Dec 5, 2025
97aecf4
ci: Add virtual environment creation step in GitHub Actions workflows
disafronov Dec 5, 2025
e335c3b
ci: Update version extraction command in GitHub Actions workflows
disafronov Dec 5, 2025
e9a354f
chore(deps): bump astral-sh/setup-uv from 3 to 7
dependabot[bot] Dec 5, 2025
02d2136
refactor: Update type hints for error classes in errors.py
disafronov Dec 5, 2025
a8af09a
refactor(schema_loader): add caching to get_builtin_logrecord_attributes
disafronov Dec 5, 2025
10fc5c3
refactor(schema_loader): extract path formatting into helper function
disafronov Dec 5, 2025
a6533b0
refactor(schema_loader): introduce _is_empty_or_none helper function
disafronov Dec 5, 2025
f52dd78
refactor(schema_applier): update type hints to Python 3.9+ syntax
disafronov Dec 5, 2025
80ae0cb
refactor(schema_loader): update type hints to Python 3.9+ syntax
disafronov Dec 5, 2025
d4d08c7
chore(release): 0.1.1-rc.2 [skip ci]
semantic-release-bot Dec 5, 2025
6cb5ec0
refactor(schema_loader): introduce _validate_and_create_leaf function
disafronov Dec 5, 2025
1402780
test(schema_loader): add unit tests for schema validation functions
disafronov Dec 5, 2025
e9265ae
test(schema_loader): add tests for schema depth validation and path r…
disafronov Dec 5, 2025
26eeecc
ci(releaserc): remove [skip ci] from release message format
disafronov Dec 5, 2025
803d647
chore: update logging-objects-with-schema version to 0.1.1rc2
disafronov Dec 5, 2025
750aa26
chore(release): 0.1.1-rc.3
semantic-release-bot Dec 5, 2025
9ee3bbb
chore(release): update release preparation commands and assets
disafronov Dec 5, 2025
5962576
refactor(schema_loader): add caching functions for schema file paths
disafronov Dec 5, 2025
ab0e346
chore(release): 0.1.1-rc.4
semantic-release-bot Dec 5, 2025
5fef25f
refactor(schema_applier): simplify value retrieval from extra_values
disafronov Dec 5, 2025
804ed64
refactor(schema_loader): consolidate exception handling in schema com…
disafronov Dec 5, 2025
edcf85f
refactor(schema_loader): remove unused variable in schema compilation
disafronov Dec 5, 2025
fe80bb2
refactor(schema_loader): create helper function for empty schema with…
disafronov Dec 5, 2025
192ad56
refactor(schema_applier): optimize source tracking in schema application
disafronov Dec 5, 2025
0025524
refactor(schema_loader): extract current working directory logic into…
disafronov Dec 5, 2025
fd52b6b
refactor(schema_loader): enhance schema loading tests and add new hel…
disafronov Dec 5, 2025
0bc1a6c
refactor(schema_logger): extract logger cleanup logic into a helper m…
disafronov Dec 5, 2025
6abaf80
refactor(schema_loader): add helper function to identify leaf nodes i…
disafronov Dec 5, 2025
a9abcb4
test(schema_loader): add unit tests for _is_leaf_node function
disafronov Dec 5, 2025
b4a00d1
refactor(schema_loader): simplify schema path resolution in compilation
disafronov Dec 5, 2025
78d2877
refactor(schema_logger): enhance exception handling during schema com…
disafronov Dec 5, 2025
2f0d6e9
docs(README): clarify exception handling for schema validation
disafronov Dec 5, 2025
baa36c8
docs(README): add handling for system-level errors during logger init…
disafronov Dec 5, 2025
f6106bc
refactor(schema_applier): optimize redundant field reporting in schem…
disafronov Dec 5, 2025
0ff75b1
docs(schema_applier): clarify type checking for list validation
disafronov Dec 5, 2025
ed8e214
docs: update exception handling for system-level errors
disafronov Dec 5, 2025
328b07a
refactor(schema_loader): update _load_raw_schema to accept schema_pat…
disafronov Dec 5, 2025
c922177
refactor(schema_loader): improve thread safety in schema compilation
disafronov Dec 5, 2025
6e63a36
chore(release): 0.1.1-rc.5
semantic-release-bot Dec 6, 2025
21637eb
docs: enhance README and comments for system-level error handling
disafronov Dec 6, 2025
6f2e1e9
ci: add GitHub Actions workflow for automatic PR description generation
disafronov Dec 6, 2025
33b3bb2
ci: update GitHub Actions workflow permissions for PR handling
disafronov Dec 6, 2025
bd531cb
ci: update PR description generation action and output variable
disafronov Dec 6, 2025
515509c
ci: update PR description generation action to stable version
disafronov Dec 6, 2025
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
45 changes: 45 additions & 0 deletions .github/workflows/auto-pr-description.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: Force Release PR

on:
pull_request:
types:
- opened
- synchronize
- reopened
branches:
- release

jobs:
force-release-pr:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
if: github.event.pull_request.head.ref == 'main'

steps:
- uses: actions/checkout@v4

- name: Generate PR description
id: gen
uses: tanmay-pathak/generate-pull-request-description@v1.0.0
with:
pull_request_url: ${{ github.event.pull_request.url }}
api_token: ${{ secrets.GITHUB_TOKEN }}

- name: Force overwrite PR title and body
uses: actions/github-script@v7
env:
PR_BODY: ${{ steps.gen.outputs.pull_request_description }}
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const now = new Date().toISOString().slice(0,16).replace('T',' ');
const body = process.env.PR_BODY;
await github.rest.pulls.update({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.payload.pull_request.number,
title: `Release PR for ${now}`,
body: body
});
2 changes: 1 addition & 1 deletion .github/workflows/lint_and_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
uses: actions/checkout@v6

- name: Install uv
uses: astral-sh/setup-uv@v3
uses: astral-sh/setup-uv@v7
with:
enable-cache: true
cache-suffix: ${{ matrix.python-version }}
Expand Down
52 changes: 52 additions & 0 deletions .github/workflows/publish-stable.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
---
name: Publish to PyPI (stable)

"on":
push:
tags:
# Publish final release tags (without -rc suffix).
- "v[0-9]+.[0-9]+.[0-9]+"

jobs:
publish:
name: "Publish to PyPI"
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- name: Checkout
uses: actions/checkout@v6

- name: Install uv
uses: astral-sh/setup-uv@v7
with:
enable-cache: true

- name: Create virtual environment
run: uv venv

- name: Verify version matches tag
run: |
TAG_NAME="${GITHUB_REF#refs/tags/}"
# Remove 'v' prefix from tag (v1.2.3 -> 1.2.3)
EXPECTED_VERSION=$(echo "$TAG_NAME" | sed 's/^v//')
# Extract version from pyproject.toml using tomli (compatible with Python 3.7+)
uv pip install tomli
ACTUAL_VERSION=$(uv run python -c "import tomli; f=open('pyproject.toml','rb'); data=tomli.load(f); print(data['project']['version'])")
if [ "$EXPECTED_VERSION" != "$ACTUAL_VERSION" ]; then
echo "Error: Version mismatch!"
echo "Tag: $TAG_NAME"
echo "Expected version in pyproject.toml: $EXPECTED_VERSION"
echo "Actual version in pyproject.toml: $ACTUAL_VERSION"
exit 1
fi
echo "Version verification passed: $ACTUAL_VERSION"

- name: Build package
run: uv build

- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages-dir: dist/
53 changes: 53 additions & 0 deletions .github/workflows/publish.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
name: Publish Release Candidate to Test PyPI

"on":
push:
tags:
# Publish release candidate tags.
- "v[0-9]+.[0-9]+.[0-9]+-rc.[0-9]+"

jobs:
publish-rc:
name: "Publish RC to Test PyPI"
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- name: Checkout
uses: actions/checkout@v6

- name: Install uv
uses: astral-sh/setup-uv@v7
with:
enable-cache: true

- name: Create virtual environment
run: uv venv

- name: Verify version matches tag
run: |
TAG_NAME="${GITHUB_REF#refs/tags/}"
# Convert SemVer tag format (v1.2.3-rc.1) to PEP 440 format (1.2.3rc1)
EXPECTED_VERSION=$(echo "$TAG_NAME" | sed 's/^v//' | sed 's/-rc\./rc/')
# Extract version from pyproject.toml using tomli (compatible with Python 3.7+)
uv pip install tomli
ACTUAL_VERSION=$(uv run python -c "import tomli; f=open('pyproject.toml','rb'); data=tomli.load(f); print(data['project']['version'])")
if [ "$EXPECTED_VERSION" != "$ACTUAL_VERSION" ]; then
echo "Error: Version mismatch!"
echo "Tag: $TAG_NAME"
echo "Expected version in pyproject.toml: $EXPECTED_VERSION"
echo "Actual version in pyproject.toml: $ACTUAL_VERSION"
exit 1
fi
echo "Version verification passed: $ACTUAL_VERSION"

- name: Build package
run: uv build

- name: Publish to Test PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages-dir: dist/
repository-url: https://test.pypi.org/legacy/
34 changes: 34 additions & 0 deletions .github/workflows/release-stable.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
name: Release (stable)

"on":
push:
branches:
- release

jobs:
release:
name: "Release"
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
concurrency:
group: semantic-release
cancel-in-progress: false
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
token: ${{ secrets.SEMANTIC_RELEASE_TOKEN || secrets.GITHUB_TOKEN }}

- name: Semantic release
run: |
docker run --rm \
--user 1001 \
-v ${{ github.workspace }}:/workspace \
-w /workspace \
-e GITHUB_TOKEN=${{ secrets.SEMANTIC_RELEASE_TOKEN || secrets.GITHUB_TOKEN }} \
-e CI=true \
ghcr.io/disafronov/semantic-release:latest
58 changes: 32 additions & 26 deletions .releaserc.json
Original file line number Diff line number Diff line change
@@ -1,30 +1,36 @@
{
"branches": ["main"],
"branches": [
"release",
{
"name": "main",
"prerelease": "rc"
}
],
"plugins": [
["@semantic-release/commit-analyzer", {
"preset": "conventionalcommits",
"releaseRules": [
{ "type": "feat", "release": "minor" },
{ "type": "fix", "release": "patch" },
{ "type": "perf", "release": "patch" },
{ "type": "revert", "release": "patch" },
{ "type": "refactor", "release": "patch" },
{ "type": "docs", "release": false },
{ "type": "style", "release": false },
{ "type": "test", "release": false },
{ "type": "build", "release": false },
{ "type": "ci", "release": false },
{ "type": "chore", "release": false }
]
}],
["@semantic-release/release-notes-generator", { "preset": "conventionalcommits" }],
["@semantic-release/exec", {
"prepareCmd": "node -e \"const fs=require('fs'),toml=require('@iarna/toml');const f='pyproject.toml';const data=toml.parse(fs.readFileSync(f,'utf8'));data.project.version='${nextRelease.version}';fs.writeFileSync(f,toml.stringify(data))\""
}],
["@semantic-release/git", {
"assets": ["pyproject.toml"],
"message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
}],
["@semantic-release/github", {}]
["@semantic-release/commit-analyzer", {
"preset": "conventionalcommits",
"releaseRules": [
{ "type": "feat", "release": "minor" },
{ "type": "fix", "release": "patch" },
{ "type": "perf", "release": "patch" },
{ "type": "revert", "release": "patch" },
{ "type": "refactor", "release": "patch" },
{ "type": "docs", "release": false },
{ "type": "style", "release": false },
{ "type": "test", "release": false },
{ "type": "build", "release": false },
{ "type": "ci", "release": false },
{ "type": "chore", "release": false }
]
}],
["@semantic-release/release-notes-generator", { "preset": "conventionalcommits" }],
["@semantic-release/exec", {
"prepareCmd": "node -e \"const fs=require('fs'),toml=require('@iarna/toml');let version='${nextRelease.version}';version=version.replace(/-rc\\\\./g,'rc');const pyprojectFile='pyproject.toml';const pyprojectData=toml.parse(fs.readFileSync(pyprojectFile,'utf8'));const packageName=pyprojectData.project.name;pyprojectData.project.version=version;fs.writeFileSync(pyprojectFile,toml.stringify(pyprojectData));const uvLockFile='uv.lock';const uvLockData=toml.parse(fs.readFileSync(uvLockFile,'utf8'));const packageIndex=uvLockData.package.findIndex(p=>p.name===packageName);if(packageIndex!==-1){uvLockData.package[packageIndex].version=version;fs.writeFileSync(uvLockFile,toml.stringify(uvLockData));}\""
}],
["@semantic-release/git", {
"assets": ["pyproject.toml", "uv.lock"],
"message": "chore(release): ${nextRelease.version}\n\n${nextRelease.notes}"
}],
["@semantic-release/github", {}]
]
}
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,13 @@ except SchemaValidationError as e:
print(f" - {problem.message}")
# Decide whether to abort or continue with default logger
raise
except (OSError, ValueError, RuntimeError) as e:
# System-level errors (e.g., inaccessible working directory when os.getcwd()
# fails, lock failures, path resolution issues) are raised directly, not
# wrapped in SchemaValidationError. Note: OSError when reading the schema
# file is converted to SchemaValidationError and handled above.
print(f"System error during logger initialization: {e}")
raise

# When logging, handle DataValidationError
try:
Expand Down Expand Up @@ -323,6 +330,21 @@ consistent type expectations when reusing a `source` field.
The application decides whether `SchemaValidationError` is a fatal error that
should abort startup, or whether it should be logged and ignored.

**Note**: In rare cases, system-level errors may be raised directly instead of
being wrapped in `SchemaValidationError`. Specifically:

- `OSError` when the current working directory is inaccessible or deleted (e.g.,
when `os.getcwd()` fails) is propagated as-is to indicate environmental issues.
However, `OSError` that occurs when reading the schema file (e.g., permission
denied, I/O errors) is converted to `SchemaValidationError` and reported as a
schema problem.
- `ValueError` when path resolution fails due to invalid characters or malformed
paths during schema file discovery is propagated as-is.
- `RuntimeError` when thread lock acquisition fails is propagated as-is.

Applications should handle these exceptions separately if they need to
distinguish between schema validation failures and system-level errors.

## Schema caching and thread safety

- The library caches compiled schemas to avoid recompiling the same schema file
Expand Down
Loading