Skip to content

Commit b4987f2

Browse files
Merge pull request #41 from codefly-dev/fix/test-container-ownership
Fix FastAPI release qualification and generated scaffold lint
2 parents b8191e9 + 22db1a8 commit b4987f2

10 files changed

Lines changed: 48 additions & 14 deletions

File tree

‎agent.codefly.yaml‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,6 @@ publisher: codefly.dev
22
kind: codefly:service
33
name: python-fastapi
44
version: 0.0.100
5+
source:
6+
directory: .
7+
agent: codefly.dev/go:0.0.51

‎destroy_test.go‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,7 @@ func TestResolveRuntimeImageHonorsOverride(t *testing.T) {
297297
// that is the shape `codefly` shutdown reaches when Init never ran in this
298298
// process, and the only path on which Destroy reaches the container by name.
299299
func TestDestroyRemovesContainerBeforeClearingCache(t *testing.T) {
300+
ownTestContainers(t)
300301
ctx := context.Background()
301302

302303
// Docker on macOS only bind-mounts shared paths, and the per-user temp dir

‎lifecycle_matrix_test.go‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ import (
1010

1111
"github.com/codefly-dev/core/resources"
1212
runners "github.com/codefly-dev/core/runners/base"
13+
"github.com/codefly-dev/core/runners/dockerrun"
1314
"github.com/codefly-dev/core/runners/testmatrix"
15+
"github.com/stretchr/testify/require"
1416
)
1517

1618
// TestPythonFastAPILifecycle_Matrix exercises python-fastapi's parity
@@ -19,6 +21,14 @@ import (
1921
// (main.go `runtimeImage`). Nix + native rely on host's python3 via PATH
2022
// or flake.nix respectively.
2123
func TestPythonFastAPILifecycle_Matrix(t *testing.T) {
24+
// The test binary owns its containers independently of the source-test launcher.
25+
root := t.TempDir()
26+
scope, err := dockerrun.NewContainerRecoveryScope(root, root, t.Name())
27+
require.NoError(t, err)
28+
t.Setenv(dockerrun.ContainerRecoveryScopeEnvironment, os.Getenv(dockerrun.ContainerRecoveryScopeEnvironment))
29+
require.NoError(t, dockerrun.SetContainerRecoveryScope(scope))
30+
require.NotEmpty(t, dockerrun.InheritedContainerRecoveryScope())
31+
2232
dir, err := os.MkdirTemp("", "pyfastapi-matrix-*")
2333
if err != nil {
2434
t.Fatalf("mkdtemp: %v", err)

‎main_test.go‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
builderv0 "github.com/codefly-dev/core/generated/go/codefly/services/builder/v0"
2121

2222
"github.com/codefly-dev/core/resources"
23+
"github.com/codefly-dev/core/runners/dockerrun"
2324

2425
basev0 "github.com/codefly-dev/core/generated/go/codefly/base/v0"
2526
)
@@ -31,6 +32,7 @@ func TestCreateToRunNative(t *testing.T) {
3132
}
3233

3334
func TestCreateToRunDocker(t *testing.T) {
35+
ownTestContainers(t)
3436
testCreateToRun(t, resources.NewRuntimeContextContainer())
3537
}
3638

@@ -166,3 +168,15 @@ func testRun(t *testing.T, runtime *Runtime, ctx context.Context, identity *base
166168
break
167169
}
168170
}
171+
172+
// Source tests run below the agent process, so its recovery marker is not ours.
173+
// Give test-owned resources a new isolated scope; never remove the ownership check.
174+
func ownTestContainers(t *testing.T) {
175+
t.Helper()
176+
root := t.TempDir()
177+
scope, err := dockerrun.NewContainerRecoveryScope(root, root, t.Name())
178+
require.NoError(t, err)
179+
t.Setenv(dockerrun.ContainerRecoveryScopeEnvironment, os.Getenv(dockerrun.ContainerRecoveryScopeEnvironment))
180+
require.NoError(t, dockerrun.SetContainerRecoveryScope(scope))
181+
require.NotEmpty(t, dockerrun.InheritedContainerRecoveryScope())
182+
}
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
from fastapi import APIRouter
22

3-
from src.admin.version import get_version
43
from src.admin.models import Version
4+
from src.admin.version import get_version
55

66
router = APIRouter()
77

8+
89
@router.get("/version", response_model=Version)
910
async def version():
1011
return get_version()
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
import codefly_sdk.codefly as codefly
1+
from codefly_sdk import codefly
2+
23
from src.admin.models import Version
34

5+
46
def get_version() -> Version:
57
return Version(version=codefly.get_version())

‎templates/factory/code/src/framework/plugin.py.tmpl‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1+
from collections.abc import Callable
12
from dataclasses import dataclass, field
2-
from typing import Optional, Callable
33

44
from fastapi import APIRouter
55

@@ -16,6 +16,6 @@ class Plugin:
1616
router: APIRouter
1717
prefix: str = ""
1818
tags: list[str] = field(default_factory=list)
19-
startup: Optional[Callable] = None
20-
shutdown: Optional[Callable] = None
19+
startup: Callable | None = None
20+
shutdown: Callable | None = None
2121
migrations: list[str] = field(default_factory=list)

‎templates/factory/code/src/main.py.tmpl‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import os
22

3+
from codefly_sdk import codefly
34
from fastapi import FastAPI
45
from fastapi.middleware.cors import CORSMiddleware
5-
import codefly_sdk.codefly as codefly
66

77

88
def _service_manifest_reachable() -> bool:
@@ -38,8 +38,10 @@ app.add_middleware(
3838
allow_headers=["*"],
3939
)
4040

41+
# Initialize configuration before importing routes or user-provided plugins.
4142
# Routes
4243
from src.admin.router import router as admin
44+
4345
app.include_router(admin)
4446

4547
# Plugins

‎templates/factory/code/src/openapi.py.tmpl‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
import json
44
import os
55

6-
from src.main import app
7-
8-
import codefly_sdk.codefly as codefly
6+
from codefly_sdk import codefly
97
from fastapi.openapi.utils import get_openapi
108

9+
from src.main import app
10+
1111
if __name__ == "__main__":
1212
current_file_path = os.path.abspath(__file__)
1313
openapi_dir = os.path.abspath(os.path.join(current_file_path, "../../../openapi"))

‎templates/factory/code/tests/admin/test_admin.py.tmpl‎

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,18 @@ os.environ.setdefault("CODEFLY__SERVICE", "svc")
1010
os.environ.setdefault("CODEFLY__SERVICE_VERSION", "0.0.0")
1111

1212
import pytest
13-
from httpx import AsyncClient, ASGITransport
13+
from httpx import ASGITransport, AsyncClient
1414

15-
from src.main import app
16-
17-
from src.admin.version import get_version
1815
from src.admin.models import Version
16+
from src.admin.version import get_version
17+
from src.main import app
1918

2019

2120
@pytest.mark.asyncio
2221
async def test_version():
23-
async with AsyncClient(transport=ASGITransport(app=app), base_url="http://localhost:8080") as ac:
22+
async with AsyncClient(
23+
transport=ASGITransport(app=app), base_url="http://localhost:8080"
24+
) as ac:
2425
response = await ac.get("/version")
2526
assert response.status_code == 200
2627

0 commit comments

Comments
 (0)