Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

history fixes #130

Merged
merged 7 commits into from
Dec 2, 2024
Merged
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
12 changes: 8 additions & 4 deletions controller/thymis_controller/dependencies.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import datetime
import logging
import threading
import uuid
from typing import Annotated, Generator, Optional, Union

Expand All @@ -16,15 +17,18 @@

global_project = None
SESSION_LIFETIME = datetime.timedelta(days=1)
project_lock = threading.Lock()


def get_project():
global global_project
if global_project is None:
REPO_PATH = global_settings.REPO_PATH.resolve()

global_project = Project(REPO_PATH, next(get_db_session()))
return global_project
with project_lock:
if global_project is None:
REPO_PATH = global_settings.REPO_PATH.resolve()

global_project = Project(REPO_PATH, next(get_db_session()))
return global_project


def get_state(project: Project = Depends(get_project)):
Expand Down
2 changes: 2 additions & 0 deletions controller/thymis_controller/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from .device import *
from .history import *
from .module import *
from .state import *
from .task import *
Expand All @@ -10,6 +11,7 @@
+ task.__all__ # pylint: disable=undefined-variable
+ web_session.__all__ # pylint: disable=undefined-variable
+ device.__all__ # pylint: disable=undefined-variable
+ history.__all__ # pylint: disable=undefined-variable
)

# See https://stackoverflow.com/questions/60440945/correct-way-to-re-export-modules-from-init-py
21 changes: 21 additions & 0 deletions controller/thymis_controller/models/history.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import datetime
from typing import List

from pydantic import BaseModel


class Commit(BaseModel):
SHA: str
SHA1: str
message: str
date: datetime.datetime
author: str
state_diff: List[str]


class Remote(BaseModel):
name: str
url: str


__all__ = ["Commit", "Remote"]
55 changes: 37 additions & 18 deletions controller/thymis_controller/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import subprocess
import sys
import tempfile
import threading
import traceback
from pathlib import Path
from typing import List
Expand All @@ -16,6 +17,7 @@
from sqlalchemy.orm import Session
from thymis_controller import crud, migration, models, task
from thymis_controller.config import global_settings
from thymis_controller.models import history
from thymis_controller.models.state import State
from thymis_controller.nix import NIX_CMD, get_input_out_path, render_flake_nix

Expand Down Expand Up @@ -126,6 +128,7 @@ class Project:
repo: git.Repo
known_hosts_path: pathlib.Path
public_key: str
history_lock = threading.Lock()

def __init__(self, path, db_session: Session):
self.path = pathlib.Path(path)
Expand Down Expand Up @@ -240,23 +243,32 @@ def commit(self, summary: str):
self.repo.index.commit(summary)

def get_history(self):
return [
{
"message": commit.message,
"author": commit.author.name,
"date": commit.authored_datetime,
"SHA": commit.hexsha,
"SHA1": self.repo.git.rev_parse(commit.hexsha, short=True),
"state_diff": self.repo.git.diff(
commit.hexsha,
commit.parents[0].hexsha if len(commit.parents) > 0 else None,
"-R",
"state.json",
unified=5,
).split("\n")[4:],
}
for commit in self.repo.iter_commits()
]
try:
with self.history_lock:
return [
history.Commit(
message=commit.message,
author=commit.author.name,
date=commit.authored_datetime,
SHA=commit.hexsha,
SHA1=self.repo.git.rev_parse(commit.hexsha, short=True),
state_diff=self.repo.git.diff(
commit.hexsha,
(
commit.parents[0].hexsha
if len(commit.parents) > 0
else None
),
"-R",
"state.json",
unified=5,
).split("\n")[4:],
)
for commit in self.repo.iter_commits()
]
except Exception:
traceback.print_exc()
return []

def update_known_hosts(self, db_session: Session):
if not self.known_hosts_path or not self.known_hosts_path.exists():
Expand Down Expand Up @@ -293,6 +305,9 @@ def clone_state_device(
state.devices.append(new_device)
self.write_state_and_reload(state)

def get_remotes(self):
return [history.Remote(name=r.name, url=r.url) for r in self.repo.remotes]

def create_build_task(self):
return task.global_task_controller.add_task(task.BuildProjectTask(self.path))

Expand All @@ -304,7 +319,11 @@ def create_deploy_device_task(self, device_identifier: str, target_host: str):
)
return task.global_task_controller.add_task(
task.DeployDeviceTask(
self.path, device, target_host, global_settings.SSH_KEY_PATH
self.path,
device,
global_settings.SSH_KEY_PATH,
self.known_hosts_path,
target_host,
)
)

Expand Down
9 changes: 7 additions & 2 deletions controller/thymis_controller/routers/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,12 +145,12 @@ def download_image(
raise HTTPException(status_code=404, detail="Image not found")


@router.get("/history")
@router.get("/history", tags=["history"])
def get_history(project: project.Project = Depends(get_project)):
return project.get_history()


@router.post("/history/revert-commit")
@router.post("/history/revert-commit", tags=["history"])
def revert_commit(
commit_sha: str,
project: project.Project = Depends(get_project),
Expand All @@ -159,6 +159,11 @@ def revert_commit(
return {"message": "reverted commit"}


@router.get("/history/remotes", tags=["history"])
def get_remotes(project: project.Project = Depends(get_project)):
return project.get_remotes()


@router.post("/action/update")
async def update(
project: project.Project = Depends(get_project),
Expand Down
3 changes: 1 addition & 2 deletions controller/thymis_controller/routers/frontend.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,13 +84,12 @@ async def run(self):

# read stdout and stderr in background
async def read_stream(stream: asyncio.StreamReader, level=logging.INFO):
while self.process.returncode is None and not self.stopped:
while not stream.at_eof():
line = await stream.readline()
if line:
logger.log(
level, "frontend process: %s", line.decode("utf-8").strip()
)
await asyncio.sleep(0.001)

# start threads
asyncio.create_task(read_stream(self.process.stdout))
Expand Down
13 changes: 13 additions & 0 deletions frontend/src/lib/history.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export type Commit = {
message: string;
author: string;
date: string;
SHA: string;
SHA1: string;
state_diff: string[];
};

export type Remote = {
name: string;
url: string;
};
7 changes: 4 additions & 3 deletions frontend/src/routes/(authenticated)/history/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@
import DeployActions from '$lib/components/DeployActions.svelte';
import Undo from 'lucide-svelte/icons/undo-2';
import RollbackModal from './RollbackModal.svelte';
import type { Commit } from '$lib/history';

export let data: PageData;

let revertCommit: { SHA1: string; message: string } | undefined;
let revertCommit: Commit | undefined;

const lineColor = (line: string) => {
if (line.startsWith('+')) {
Expand Down Expand Up @@ -42,15 +43,15 @@
<span class="text-gray-400 dark:text-gray-600"> with hash {history.SHA1}</span>
</div>
<div class="shrink">
<Button
<!-- <Button
class="p-2 mr-2 w-full flex justify-center gap-2 rounded"
color="alternative"
on:click={() => (revertCommit = history)}
disabled={index === 0}
>
<Undo />
{$t('history.revert-commit-button')}
</Button>
</Button> -->
<Tooltip type="auto">
<P size="sm">
{#if index === 0}
Expand Down
19 changes: 8 additions & 11 deletions frontend/src/routes/(authenticated)/history/+page.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
import type { Commit } from '$lib/history';
import type { PageLoad } from './$types';

export const load = (async ({ fetch }) => {
const response = await fetch(`/api/history`, {
const history_response = fetch(`/api/history`, {
method: 'GET',
headers: {
'content-type': 'application/json'
}
}).then((res) => {
if (!res.ok) {
throw new Error(`Failed to fetch history: ${res.status} ${res.statusText}`);
}
return res.json() as Promise<Commit[]>;
});
return {
history: response.json() as Promise<
{
message: string;
author: string;
date: string;
SHA: string;
SHA1: string;
state_diff: string[];
}[]
>
history: history_response
};
}) satisfies PageLoad;
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
import { t } from 'svelte-i18n';
import { invalidate } from '$app/navigation';
import { Button, Modal } from 'flowbite-svelte';
import type { Commit } from '$lib/history';

export let commit: { SHA1: string; message: string } | undefined;
export let commit: Commit | undefined;

const revertCommit = async (commitSHA: string | undefined) => {
if (commitSHA === undefined) return;
Expand Down
Loading