Skip to content
Closed
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
24 changes: 24 additions & 0 deletions .github/workflows/release-please.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: release-please

# Cuts versioned contract-checkpoint releases (tag + GitHub release + CHANGELOG)
# from conventional commits. These are contract snapshots, NOT a deploy gate.

on:
push:
branches:
- main
workflow_dispatch:

permissions:
contents: write
pull-requests: write

jobs:
release-please:
if: github.repository == 'scaleapi/scale-agentex'
runs-on: ubuntu-latest
steps:
- uses: googleapis/release-please-action@5c625bfb5d1ff62eadeeb3772007f7f66fdcf071 # v4.4.1
with:
config-file: release-please-config.json
manifest-file: .release-please-manifest.json
3 changes: 3 additions & 0 deletions .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
".": "0.1.0"
}
3 changes: 3 additions & 0 deletions agentex/src/_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"""Single source of the agentex contract version (bumped by release-please)."""

__version__ = "0.1.0" # x-release-please-version
4 changes: 4 additions & 0 deletions agentex/src/api/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from fastapi.responses import JSONResponse
from fastapi.staticfiles import StaticFiles

from src._version import __version__
from src.adapters.crud_store.exceptions import ItemDoesNotExist
from src.adapters.http.adapter_httpx import HttpxGateway
from src.api.authentication_middleware import AgentexAuthMiddleware
Expand All @@ -42,6 +43,7 @@
task_retention,
tasks,
)
from src.api.version_header_middleware import VersionHeaderMiddleware
from src.config import dependencies
from src.config.dependencies import (
GlobalDependencies,
Expand Down Expand Up @@ -108,6 +110,7 @@ async def lifespan(_: FastAPI):

fastapi_app = FastAPI(
title="Agentex API",
version=__version__,
openapi_url="/openapi.json",
docs_url="/swagger",
redoc_url="/api",
Expand Down Expand Up @@ -137,6 +140,7 @@ async def lifespan(_: FastAPI):
# Add Authentication middleware
fastapi_app.add_middleware(AgentexAuthMiddleware)
fastapi_app.add_middleware(RequestLoggingMiddleware)
fastapi_app.add_middleware(VersionHeaderMiddleware)

# Mount the MkDocs site
docs_path = Path(__file__).parent.parent.parent / "docs" / "site"
Expand Down
30 changes: 30 additions & 0 deletions agentex/src/api/version_header_middleware.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"""ASGI middleware that advertises the server's contract version on responses."""

from __future__ import annotations

from starlette.datastructures import MutableHeaders
from starlette.types import ASGIApp, Message, Receive, Scope, Send

from src._version import __version__

VERSION_HEADER = "x-agentex-version"


class VersionHeaderMiddleware:
"""Set `X-Agentex-Version` on every HTTP response so clients can detect a
server whose contract version is incompatible with their build."""

def __init__(self, app: ASGIApp) -> None:
self.app = app

async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
if scope["type"] != "http":
await self.app(scope, receive, send)
return

async def send_with_version(message: Message) -> None:
if message["type"] == "http.response.start":
MutableHeaders(scope=message)[VERSION_HEADER] = __version__
await send(message)

await self.app(scope, receive, send_with_version)
22 changes: 22 additions & 0 deletions agentex/tests/unit/api/test_version_header_middleware.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
"""Unit tests for VersionHeaderMiddleware — sets X-Agentex-Version on responses."""

import pytest
from src._version import __version__
from src.api.version_header_middleware import VERSION_HEADER, VersionHeaderMiddleware
from starlette.applications import Starlette
from starlette.responses import PlainTextResponse
from starlette.routing import Route
from starlette.testclient import TestClient


@pytest.mark.unit
def test_sets_version_header_on_responses():
def endpoint(request):
return PlainTextResponse("ok")

wrapped = VersionHeaderMiddleware(Starlette(routes=[Route("/x", endpoint)]))
client = TestClient(wrapped)

response = client.get("/x")
assert response.status_code == 200
assert response.headers[VERSION_HEADER] == __version__
32 changes: 32 additions & 0 deletions release-please-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json",
"include-v-in-tag": true,
"include-component-in-tag": false,
"bump-minor-pre-major": true,
"bump-patch-for-minor-pre-major": false,
"bootstrap-sha": "ab469df91bba043ea25356c89147d29f7df03bad",
"changelog-sections": [
{ "type": "feat", "section": "Features" },
{ "type": "fix", "section": "Bug Fixes" },
{ "type": "perf", "section": "Performance Improvements" },
{ "type": "revert", "section": "Reverts" },
{ "type": "docs", "section": "Documentation" },
{ "type": "refactor", "section": "Refactors" },
{ "type": "chore", "section": "Chores", "hidden": true },
{ "type": "test", "section": "Tests", "hidden": true },
{ "type": "ci", "section": "Continuous Integration", "hidden": true },
{ "type": "build", "section": "Build System", "hidden": true },
{ "type": "style", "section": "Styles", "hidden": true }
],
"packages": {
".": {
"release-type": "python",
"package-name": "agentex",
"extra-files": [
"agentex/src/_version.py",
{ "type": "yaml", "path": "agentex/openapi.yaml", "jsonpath": "$.info.version" },
{ "type": "toml", "path": "agentex/pyproject.toml", "jsonpath": "$.project.version" }
]
}
}
}
Loading