Skip to content

Commit

Permalink
Merge branch 'main' into make-text-selectable
Browse files Browse the repository at this point in the history
  • Loading branch information
nadzyah authored Jun 22, 2023
2 parents d97a72d + 62d45fd commit 2e79c4c
Show file tree
Hide file tree
Showing 15 changed files with 426 additions and 381 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
"""Use nulls not distinct
Revision ID: b33ee8dd41b1
Revises: 6a80dad01d24
Create Date: 2023-06-20 10:00:07.676129+00:00
"""
from alembic import op


# revision identifiers, used by Alembic.
revision = "b33ee8dd41b1"
down_revision = "6a80dad01d24"
branch_labels = None
depends_on = None


def upgrade() -> None:
op.execute(
"ALTER TABLE artefact_build "
"DROP CONSTRAINT IF EXISTS artefact_build_artefact_id_architecture_revision_key"
", ADD CONSTRAINT unique_artefact_build "
"UNIQUE NULLS NOT DISTINCT (artefact_id, architecture, revision);"
)


def downgrade() -> None:
op.execute(
"ALTER TABLE artefact_build "
"DROP CONSTRAINT IF EXISTS unique_artefact_build"
", ADD CONSTRAINT artefact_build_artefact_id_architecture_revision_key "
"UNIQUE (artefact_id, architecture, revision);"
)
399 changes: 200 additions & 199 deletions backend/poetry.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion backend/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ authors = []
python = "^3.10"
fastapi = "^0.95.0"
uvicorn = {extras = ["standard"], version = "^0.21.1"}
sqlalchemy = "^2.0.9"
sqlalchemy = "^2.0.16"
pg8000 = "^1.29.4"
alembic = "^1.10.3"
poetry-dynamic-versioning = {extras = ["plugin"], version = "^0.22.0"}
Expand Down
2 changes: 0 additions & 2 deletions backend/test_observer/controllers/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,10 @@
from .artefacts import artefacts
from .families import families
from .promoter import promoter
from .test_execution import test_execution
from .test_executions import test_executions

router = APIRouter()
router.include_router(promoter.router)
router.include_router(test_execution.router, prefix="/v1/test-execution")
router.include_router(families.router, prefix="/v1/families")
router.include_router(version.router, prefix="/v1/version")
router.include_router(test_executions.router, prefix="/v1/test-executions")
Expand Down
Empty file.
12 changes: 0 additions & 12 deletions backend/test_observer/controllers/test_execution/models.py

This file was deleted.

82 changes: 0 additions & 82 deletions backend/test_observer/controllers/test_execution/test_execution.py

This file was deleted.

31 changes: 31 additions & 0 deletions backend/test_observer/controllers/test_executions/models.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,39 @@
# Copyright 2023 Canonical Ltd.
# All rights reserved.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Written by:
# Omar Selo <[email protected]>


from pydantic import BaseModel

from test_observer.data_access.models_enums import TestExecutionStatus


class StartTestExecutionRequest(BaseModel):
family: str
name: str
version: str
revision: int | None = None
source: dict
arch: str
execution_stage: str
environment: str


class TestExecutionsPatchRequest(BaseModel):
c3_link: str
jenkins_link: str
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,90 @@
# Copyright 2023 Canonical Ltd.
# All rights reserved.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Written by:
# Omar Selo <[email protected]>
# Nadzeya Hutsko <[email protected]>


from fastapi import APIRouter, Depends
from sqlalchemy.orm import Session

from test_observer.data_access.models import TestExecution
from test_observer.data_access.models import (
TestExecution,
Stage,
Artefact,
ArtefactBuild,
Environment,
)
from test_observer.data_access.models_enums import TestExecutionStatus
from test_observer.data_access.repository import get_or_create
from test_observer.data_access.setup import get_db

from .models import TestExecutionsPatchRequest
from .models import TestExecutionsPatchRequest, StartTestExecutionRequest

router = APIRouter()


@router.put("/start-test")
def start_test_execution(
request: StartTestExecutionRequest, db: Session = Depends(get_db)
):
stage = (
db.query(Stage)
.filter(
Stage.name == request.execution_stage,
Stage.family.has(name=request.family),
)
.one()
)

artefact = get_or_create(
db,
Artefact,
name=request.name,
version=request.version,
source=request.source,
stage_id=stage.id,
)

environment = get_or_create(
db,
Environment,
name=request.environment,
architecture=request.arch,
)

artefact_build = get_or_create(
db,
ArtefactBuild,
architecture=request.arch,
revision=request.revision,
artefact_id=artefact.id,
)

test_execution = get_or_create(
db,
TestExecution,
environment_id=environment.id,
artefact_build_id=artefact_build.id,
status=TestExecutionStatus.IN_PROGRESS,
)
return {"id": test_execution.id}


@router.patch("/{id}")
def patch_test_execution(
id: int,
Expand Down
10 changes: 9 additions & 1 deletion backend/test_observer/data_access/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,15 @@ class ArtefactBuild(Base):
back_populates="artefact_build", cascade="all, delete-orphan"
)

__table_args__ = (UniqueConstraint("artefact_id", "architecture", "revision"),)
__table_args__ = (
UniqueConstraint(
"artefact_id",
"architecture",
"revision",
name="unique_artefact_build",
postgresql_nulls_not_distinct=True,
),
)


class Environment(Base):
Expand Down
6 changes: 3 additions & 3 deletions backend/tests/controllers/artefacts/test_artefacts.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,19 @@
from sqlalchemy.orm import Session
from test_observer.data_access.models import ArtefactBuild, Environment, TestExecution

from tests.helpers import create_artefact, create_artefact_builds
from tests.helpers import create_artefact


def test_get_artefact_builds(db_session: Session, test_client: TestClient):
artefact = create_artefact(db_session, "beta")
artefact_build = create_artefact_builds(db_session, artefact, 1)[0]
artefact_build = ArtefactBuild(architecture="amd64", artefact=artefact, revision=1)
environment = Environment(
name="some-environment", architecture=artefact_build.architecture
)
test_execution = TestExecution(
artefact_build=artefact_build, environment=environment
)
db_session.add_all([environment, test_execution])
db_session.add_all([environment, test_execution, artefact_build])
db_session.commit()

response = test_client.get(f"/v1/artefacts/{artefact.id}/builds")
Expand Down
16 changes: 13 additions & 3 deletions backend/tests/controllers/promoter/test_promoter.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@
from fastapi.testclient import TestClient
from requests_mock import Mocker
from sqlalchemy.orm import Session
from test_observer.data_access.models import ArtefactBuild

from tests.helpers import create_artefact, create_artefact_builds
from tests.helpers import create_artefact


def test_run_to_move_artefact_snap(
Expand All @@ -45,7 +46,6 @@ def test_run_to_move_artefact_snap(
source={"store": "ubuntu"},
created_at=datetime.utcnow(),
)
create_artefact_builds(db_session, artefact)
create_artefact(
db_session,
"edge",
Expand All @@ -54,6 +54,15 @@ def test_run_to_move_artefact_snap(
source={"store": "ubuntu"},
created_at=datetime.utcnow() - timedelta(days=1),
)
db_session.add_all(
[
ArtefactBuild(architecture="amd64", artefact=artefact, revision=1),
ArtefactBuild(architecture="amd64", artefact=artefact, revision=2),
ArtefactBuild(architecture="arm64", artefact=artefact, revision=1),
]
)
db_session.commit()

requests_mock.get(
"https://api.snapcraft.io/v2/snaps/info/core20",
json={
Expand Down Expand Up @@ -106,7 +115,6 @@ def test_run_to_move_artefact_deb(
source={"series": "kinetic", "repo": "main"},
created_at=datetime.utcnow(),
)
create_artefact_builds(db_session, artefact)
create_artefact(
db_session,
"proposed",
Expand All @@ -115,6 +123,8 @@ def test_run_to_move_artefact_deb(
source={"series": "kinetic", "repo": "main"},
created_at=datetime.utcnow() - timedelta(days=1),
)
db_session.add(ArtefactBuild(architecture="amd64", artefact=artefact))
db_session.commit()

with open("tests/test_data/Packages-proposed.gz", "rb") as f:
proposed_content = f.read()
Expand Down
Loading

0 comments on commit 2e79c4c

Please sign in to comment.