Skip to content

Commit

Permalink
Merge pull request #108 from lsst-sqre/u/jsickcodes/tracked-ref-v2
Browse files Browse the repository at this point in the history
Add git_ref tracking mode
  • Loading branch information
jonathansick authored Mar 20, 2022
2 parents 0f833a8 + f64d47c commit 0a8e995
Show file tree
Hide file tree
Showing 13 changed files with 123 additions and 31 deletions.
13 changes: 8 additions & 5 deletions keeper/api/_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,13 @@ def from_edition(
task: celery.Task = None,
) -> EditionResponse:
"""Create an EditionResponse from the Edition ORM model instance."""
if edition.mode_name == "git_refs":
tracked_refs = edition.tracked_refs
elif edition.mode_name == "git_ref":
tracked_refs = [edition.tracked_ref]
else:
tracked_refs = None

obj: Dict[str, Any] = {
"self_url": url_for_edition(edition),
"product_url": url_for_product(edition.product),
Expand All @@ -271,11 +278,7 @@ def from_edition(
"date_rebuilt": edition.date_rebuilt,
"date_ended": edition.date_ended,
"mode": edition.mode_name,
"tracked_refs": (
edition.tracked_refs
if edition.mode_name == "git_refs"
else None
),
"tracked_refs": tracked_refs,
"pending_rebuild": edition.pending_rebuild,
"surrogate_key": edition.surrogate_key,
"queue_url": url_for_task(task) if task is not None else None,
Expand Down
9 changes: 4 additions & 5 deletions keeper/editiontracking/gitrefmode.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,13 @@


class GitRefTrackingMode(TrackingModeBase):
"""Default tracking mode where an edition tracks an array of Git refs.
This is the default mode if Edition.mode is None.
"""Tracking mode where an edition tracks a given git_ref (commonly
a branch).
"""

@property
def name(self) -> str:
return "git_refs"
return "git_ref"

def should_update(
self, edition: Optional[Edition], candidate_build: Optional[Build]
Expand All @@ -29,7 +28,7 @@ def should_update(
return False

if (candidate_build.product == edition.product) and (
candidate_build.git_refs == edition.tracked_refs
candidate_build.git_ref == edition.tracked_ref
):
return True
else:
Expand Down
36 changes: 36 additions & 0 deletions keeper/editiontracking/gitrefsmode.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"""Implements the ``git_refs`` tracking mode."""

from __future__ import annotations

from typing import TYPE_CHECKING, Optional

from keeper.editiontracking.base import TrackingModeBase

if TYPE_CHECKING:
from keeper.models import Build, Edition

__all__ = ["GitRefsTrackingMode"]


class GitRefsTrackingMode(TrackingModeBase):
"""Tracking mode where an edition tracks an array of Git refs.
This is the default mode if Edition.mode is None.
"""

@property
def name(self) -> str:
return "git_refs"

def should_update(
self, edition: Optional[Edition], candidate_build: Optional[Build]
) -> bool:
if edition is None or candidate_build is None:
return False

if (candidate_build.product == edition.product) and (
candidate_build.git_refs == edition.tracked_refs
):
return True
else:
return False
4 changes: 3 additions & 1 deletion keeper/editiontracking/trackingmodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from keeper.editiontracking.eupsmajormode import EupsMajorReleaseTrackingMode
from keeper.editiontracking.eupsweeklymode import EupsWeeklyReleaseTrackingMode
from keeper.editiontracking.gitrefmode import GitRefTrackingMode
from keeper.editiontracking.gitrefsmode import GitRefsTrackingMode
from keeper.editiontracking.lsstdocmode import LsstDocTrackingMode
from keeper.editiontracking.manualmode import ManualTrackingMode
from keeper.exceptions import ValidationError
Expand All @@ -21,12 +22,13 @@ class EditionTrackingModes:
"""

_modes = {
1: GitRefTrackingMode(),
1: GitRefsTrackingMode(),
2: LsstDocTrackingMode(),
3: EupsMajorReleaseTrackingMode(),
4: EupsWeeklyReleaseTrackingMode(),
5: EupsDailyReleaseTrackingMode(),
6: ManualTrackingMode(),
7: GitRefTrackingMode(),
}
"""Map of tracking mode ID (an integer stored in the DB to the tracking
mode instance that can evaluate whether an edition should be updated
Expand Down
9 changes: 8 additions & 1 deletion keeper/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,13 @@ class Edition(db.Model): # type: ignore
mode: ``git_refs``.
"""

tracked_ref = db.Column(db.Unicode(255), nullable=True)
"""The Git ref this Edition tracks and publishes if the tracking mode
is ``git_ref``.
For other tracking modes, this field may be `None`.
"""

tracked_refs = db.Column(MutableList.as_mutable(JSONEncodedVARCHAR(2048)))
"""The list of Git refs this Edition tracks and publishes if the tracking
mode is ``git_refs``.
Expand Down Expand Up @@ -956,7 +963,7 @@ def set_mode(self, mode: str) -> None:
@property
def default_mode_name(self) -> str:
"""Default tracking mode name if ``Edition.mode`` is `None` (`str`)."""
return "git_refs"
return "git_ref"

@property
def default_mode_id(self) -> int:
Expand Down
6 changes: 3 additions & 3 deletions keeper/services/createbuild.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,12 +137,12 @@ def create_autotracking_edition(
)
if edition_count == 0 and is_authorized(Permission.ADMIN_EDITION):
try:
edition_slug = auto_slugify_edition(build.git_refs)
edition_slug = auto_slugify_edition([build.git_ref])
edition = create_edition(
product=product,
title=edition_slug,
slug=edition_slug,
tracking_mode="git_refs",
tracking_mode="git_ref",
tracked_ref=build.git_ref,
)
db.session.add(edition)
Expand All @@ -152,7 +152,7 @@ def create_autotracking_edition(
"Created edition because of a build",
slug=edition.slug,
id=edition.id,
tracked_refs=edition.tracked_refs,
tracked_ref=edition.tracked_ref,
)
return edition
except Exception:
Expand Down
8 changes: 7 additions & 1 deletion keeper/services/createedition.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def create_edition(
slug.
tracked_ref : str, optional
The name of the Git ref that this edition tracks, if ``tracking_mode``
is ``"git_refs"``.
is ``"git_refs"`` or ``"git_ref"``.
build : Build, optional
The build to initially publish with this edition.
Expand All @@ -73,8 +73,14 @@ def create_edition(
else:
edition.set_mode(edition.default_mode_name)

# Set both tracked_ref and tracked_refs for the purposes of the migration
# for now
if edition.mode_name == "git_refs":
edition.tracked_refs = [tracked_ref]
edition.tracked_ref = tracked_ref
elif edition.mode_name == "git_ref":
edition.tracked_ref = tracked_ref
edition.tracked_refs = [tracked_ref]

db.session.add(edition)
db.session.commit()
Expand Down
1 change: 1 addition & 0 deletions keeper/services/updateedition.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ def update_edition(

if tracked_ref is not None:
edition.tracked_refs = [tracked_ref]
edition.tracked_ref = tracked_ref

if tracking_mode is not None:
edition.set_mode(tracking_mode)
Expand Down
25 changes: 14 additions & 11 deletions keeper/v2api/_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,7 @@ class EditionResponse(BaseModel):

tracked_ref: Optional[str]
"""Git ref that describe the version that this Edition is intended to point
to when using the ``git_refs`` tracking mode.
to when using the ``git_ref`` tracking mode.
"""

mode: str
Expand All @@ -565,6 +565,13 @@ def from_edition(
task: celery.Task = None,
) -> EditionResponse:
"""Create an EditionResponse from the Edition ORM model instance."""
if edition.mode_name == "git_ref":
tracked_ref = edition.tracked_ref
elif edition.mode_name == "git_refs":
tracked_ref = edition.tracked_refs[0]
else:
tracked_ref = None

obj: Dict[str, Any] = {
"self_url": url_for_edition(edition),
"project_url": url_for_project(edition.product),
Expand All @@ -584,11 +591,7 @@ def from_edition(
"date_rebuilt": edition.date_rebuilt,
"date_ended": edition.date_ended,
"mode": edition.mode_name,
"tracked_refs": (
edition.tracked_refs[0]
if edition.mode_name == "git_refs"
else None
),
"tracked_ref": tracked_ref,
"pending_rebuild": edition.pending_rebuild,
"surrogate_key": edition.surrogate_key,
}
Expand Down Expand Up @@ -640,8 +643,8 @@ class EditionPostRequest(BaseModel):
mode: str = "git_refs"
"""Tracking mode."""

tracked_ref: Optional[List[str]] = None
"""Git ref being tracked if mode is ``git_refs``."""
tracked_ref: Optional[str] = None
"""Git ref being tracked if mode is ``git_ref``."""

@validator("slug")
def check_slug(cls, v: Optional[str]) -> Optional[str]:
Expand Down Expand Up @@ -683,8 +686,8 @@ def check_autoincrement(cls, v: bool, values: Mapping[str, Any]) -> bool:
def check_tracked_refs(
cls, v: Optional[str], values: Mapping[str, Any]
) -> Optional[str]:
if values.get("mode") == "git_refs" and v is None:
raise ValueError('tracked_ref must be set is mode is "git_refs"')
if values.get("mode") in ("git_ref", "git_refs") and v is None:
raise ValueError('tracked_ref must be set if mode is "git_ref"')
return v


Expand All @@ -702,7 +705,7 @@ class EditionPatchRequest(BaseModel):
build.
"""

tracked_ref: Optional[List[str]] = None
tracked_ref: Optional[str] = None
"""Git ref that describes the version of the project that this this
edition is intended to point to when using the ``git_refs`` tracking mode.
"""
Expand Down
25 changes: 25 additions & 0 deletions migrations/versions/f8eeb27a49e7_add_edition_tracked_ref_column.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
"""Add Edition tracked_ref column
Revision ID: f8eeb27a49e7
Revises: febbe2d7e47b
Create Date: 2022-03-19 18:02:05.929442
"""

import sqlalchemy as sa
from alembic import op

# revision identifiers, used by Alembic.
revision = "f8eeb27a49e7"
down_revision = "febbe2d7e47b"


def upgrade():
with op.batch_alter_table("editions", schema=None) as batch_op:
batch_op.add_column(
sa.Column("tracked_ref", sa.Unicode(length=255), nullable=True)
)


def downgrade():
with op.batch_alter_table("editions", schema=None) as batch_op:
batch_op.drop_column("tracked_ref")
13 changes: 11 additions & 2 deletions tests/test_editions.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,10 @@ def test_editions(client: TestClient, mocker: Mock) -> None:
# Change the tracked_refs with PATCH
mocker.resetall()

r = client.patch(e1_url, {"tracked_refs": ["tickets/DM-9999", "main"]})
r = client.patch(
e1_url,
{"mode": "git_refs", "tracked_refs": ["tickets/DM-9999", "main"]},
)
task_queue.apply_task_side_effects()

assert r.status == 200
Expand All @@ -192,7 +195,7 @@ def test_editions(client: TestClient, mocker: Mock) -> None:
task_queue.assert_dashboard_build_v1(product_url)

# ========================================================================
# Deprecate the editon
# Deprecate the edition
mocker.resetall()

r = client.delete(e1_url)
Expand All @@ -206,6 +209,12 @@ def test_editions(client: TestClient, mocker: Mock) -> None:
# Deprecated editions no longer in the editions list
r = client.get(product_url + "/editions/")
assert r.status == 200
final_edition_urls = r.json["editions"]
print(final_edition_urls)
for f_url in final_edition_urls:
rf = client.get(f_url)
print(rf.json)

# only default edition (main) remains
assert len(r.json["editions"]) == 1

Expand Down
2 changes: 1 addition & 1 deletion tests/test_track_lsst_doc.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ def test_lsst_doc_edition(client: TestClient, mocker: Mock) -> None:

# Check that it's tracking the main branch
r = client.get(main_edition_url)
assert r.json["mode"] == "git_refs"
assert r.json["mode"] == "git_ref"
assert r.json["slug"] == "main"
assert r.json["title"] == "main"
assert r.json["tracked_refs"] == ["main"]
Expand Down
3 changes: 2 additions & 1 deletion tests/v2api/test_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def test_projects(client: TestClient, mocker: Mock) -> None:
"slug": "alpha",
"title": "Alpha",
"source_repo_url": "https://github.com/example/alpha",
"default_edition_mode": "git_refs",
"default_edition_mode": "git_ref",
}
r = client.post(org1_projects_url, request_data)
task_queue.apply_task_side_effects()
Expand Down Expand Up @@ -152,4 +152,5 @@ def test_projects(client: TestClient, mocker: Mock) -> None:
assert r.status == 200
data = r.json

# It should be tracking build 1 because it's of the main branch
assert data["build_url"] == build1_url

0 comments on commit 0a8e995

Please sign in to comment.