Skip to content

Commit

Permalink
Test Sequencer | V2 (#1138)
Browse files Browse the repository at this point in the history
* Rename Hardware Id

* Report all import pytest error after the toast.promise

* Formatting

* Better msg

* Moved Test Sequencer Project Utils File To Right Place

* Checkout point

* [fix-test-sequencer-notification] Modal Service

* [fix-test-sequencer-notification] Cleanup

* [fix-test-sequencer-notification] Moving modal in same folder

* [fix-test-sequencer-notification] Re-link Modal path

* [fix-test-sequencer-notification] Modal for long error in test discovery

* Formatting

* Formatting

* [fix-test-sequencer-notification] ESLint pipeline fix

* [fix-test-sequencer-notification] Simple eslint fix

* [TS-rename] Rename button

* [TS-rename] Rename feature | Need to double check Zustand

* All through useModalState

* Formatting

* Better state management

* Formatting

* Better Rename Modal

- Ability to see the current name
- Ability to see the underliying target

* Correct renaming of test for project

* Name + Path in Consult Code

* Formatting

* Remove unused import

* [TS-Test-Mode] Some rename

* [TS-Test-Mode] More small change

* [TS-Test-Mode] UI with selector

* Exec UI

* Test Sequencer Ctrl UI

* Rework Control UI to be incorporated in side panel

* [TS-Test-Mode] Typo

* [TS-Test-Mode] checkpoint

* [TS-Test-Mode] state on cycle

* [TS-Test-Mode] Ability to pause test sequencer | Part 1: Draft

* [TS-Test-Mode] Backend | Kill, Pause, Resume test sequencer runner

* [TS-Test-Mode] [TS-Test-Mode] Frontend | Kill, Pause, Resume test sequencer runner

* [TS-Test-Mode] Forgotten to remove the pill if this one is not ingested. OUPS

* [TS-Test-Mode] Better State Management of Running Tests

* [TS-Test-Mode] Better Looking UI to step status

* [TS-Test-Mode] Removing dead code

* [TS-Test-Mode] Toast for better knowing what's goiiiinnnng ooooonnnnnnnnnnnnnnnnnnnnnn

* [TS-Test-Mode] Cycle state management

* [TS-Test-Mode] Link with Cycle Component

* [TS-Test-Mode] Cycle Display connection

* [TS-Test-Mode] Run Cycles

* [TS-Test-Mode] Ability to check previous Cycle

* [TS-Test-Mode] UI Lock for cycle change when running

* [TS-Test-Mode] Handle Cycle in Import

* [TS-Multi-Test-Sequence] [UI] New Sequence Table

* [TS-Multi-Test-Sequence] Working UI for multisequence | WIP

* [TS-Multi-Test-Sequence] Switching between sequences | WIP

* [TS-Multi-Test-Sequence] State management sequences | WIP

* WIP commit to change computer

* [TS-Multi-Test-Sequence] Sequence the Sequence (aka Run the next sequence when the curr. one is done

- Still some cleanup to do and all. But the core functionality is now working

* [TS-Multi-Test-Sequence] Running multi sequences

* [TS-Multi-Test-Sequence] Making it clear which sequence is selected

* [TS-Multi-Test-Sequence] SetSequences (with permission) to change the sequences

* [TS-Multi-Test-Sequence] Draggable row for the sequences

* [TS-Multi-Test-Sequence] Permission to change and run

* [TS-Multi-Test-Sequence] Run only selected sequence: Done

* [TS-Multi-Test-Sequence] Completion time in sequence table

* Update src/renderer/stores/sequencer.ts

* Update src/renderer/context/testSequencerWS.context.tsx

* Update src/renderer/routes/test_sequencer_panel/components/ControlButton.tsx

* Update src/renderer/routes/test_sequencer_panel/components/ControlButton.tsx

* Update src/renderer/routes/test_sequencer_panel/components/dnd/DraggableRowSequence.tsx

* Update src/renderer/routes/test_sequencer_panel/components/dnd/DraggableRowSequence.tsx

* Update src/renderer/stores/sequencer.ts

* [TS-Multi-Test-Sequence] Removing unsaved changes Pop-Up window when importing a sequence

* [TS-Multi-Test-Sequence] Unsaved changes Pop-Up when deleting sequence

* [TS-Multi-Test-Sequence] Re-Attached Cycle (Need to be change)

* [TS-Multi-Test-Sequence] (Clean up) add / remove / change sequence

* [TS-Multi-Test-Sequence] (Clean up) Run / Run next / Update status

* [TS-Multi-Test-Sequence] (Clean up) Multi-sequence done

* [TS-Multi-Test-Sequence] (Clean up) Cycle

* [TS-Multi-Test-Sequence] (Clean up) Integrity

* [TS-Test-Mode] Infinity cycle for sequence

* [TS-Test-Mode] Better looking "Loading..." UI

* [TS-Test-Mode] Global Status + Cycle Status

* Dynamic File Dropdown base on View + Some Sequencer Keyboard shortcut

* Setting Dropdown: Removed unused button when in sequencer panel

* Better naming

* Some UI imporvement

* ProjectHandler -> SequenceHandle | In File change

* ProjectHandler -> SequenceHandler | File rename

* Multi-Sequences Select in Import

* Import by selecting Folder

* Rework notification for Import Sequences

* UI-Fix for If statement in table

* Rebuilding Tree when loaded + Redundancy check when running

* [TS-Test-Mode] @39bytes UI recommendation | Part 1

* [TS-Test-Mode] @39bytes UI suggestrion

* [TS-Test-Mode] @39bytes suggestion | + Preparing for user "technicien" open sequencer project

* [TS-Test-Mode] @39bytes UI suggestion Done

* [TS-Test-Mode] Playright test | checkpoint to develop on my Mac

* [TS-Test-Mode] Playwright base test | Missing Global Status Check

* [TS-Test-Mode] Playwright Sequencer Test Suite

* Fix Sequencer status when removing sequences

* Flowchart + Header redesign

* Sidebar UX

* Canva Background

* Watch Mode in setting | WIP

* Removing dead code

* Settings V0 -> V1 | Adding Watch Mode in Editor setting

* [TS-Test-Mode] Sequencer UI/UX redesign

* [TS-Test-Mode] Z-index on the Fail Mouse houver fix

* Loading cloud data now mimik the cloud pane

* [TS-Test-Mode] Disable Cloud Input when running test

* [TS-Test-Mode] Bug Fix: Cycle panel was below disabled element

* [TS-Test-Mode] Fix playwright test with new UI change in Sequencer

* Formatting

* [TS-Test-Mode] CI (linter) error

* Eslint fix

* Eslint fix

* Eslint fix

* For later - Simple test to upload the result while doing DFS

* formatting

* [TS-Test-Mode] Play | Stop | Resume | Pause button

* [TS-Test-Mode] Slight margin fix

* [TS-Test-Mode] z-index fix

* [TS-Test-Mode] Ptr to private instance of Flojoy Cloud

* Formatting

* Feedback -> Discord Icon

* chore: cloud panel with v1 of token

* Upload (WIP)

* Auto-Upload

* feat: auto-upload

* Working Upload

* chore: publish aborted status

* chore: publishing aborted status

* refactor(upload to cloud): removing dead code

* chore: formatting & ability to upload abort status when request fail

* chore: replace new prod url

* chore: longer timeout when requesting cloud project/station/unit/part

* chore: remove placholder for real value (station info)

* chore: tmp cache for getting workspace_id

* chore: querying the all the units for a project

* chore: autocomplete credz to: @39bytes

* feat: autocomplete serial number

* chore: uppercase serial number input

* chore: comment "load test profile"

* chore: autocomplet modify casing, auto-restore, todo: cloud should handle multiple casing

* format: frontend

* format: python

* Publish CreatedAt to cloud

* chore: format

* fix: missing property in new Test declaration

* feat: export measurement completion time

* feat: test workspack secret before setting it

* feat: test flojoy_cloud_url before setting it

* chore: format

* chore: removing env tests since it now needs a real token

* chore: removing debug code

* ci: fix playwright test sequencer

* add toastResultPromise util

* fix: cache the result of a calculation instead of re-render | removed some useless state

* fix: removing any

* [TS-Test-Mode] fix: sequencer runner - standard datetime + removing leftover artefact from upload

* [TS-Test-Mode] fix: artefact args on tsManager from removing upload

* Update captain/utils/test_sequencer/handle_data.py

Co-authored-by: Jeff Zhang <[email protected]>

* [TS-Test-Mode] Fix: str, Enum -> StrEnum

* [TS-Test-Mode] refactor: return new Promise(somethingSync) -> return somethingAsync.then(...)

* [TS-Test-Mode] fix: removing useModalState -> Directly access the store

* [TS-Test-Mode] fix: toggle export checkbox z-index

* [TS-Test-Mode] fix: Adding back flowchart project name

* [TS-Test-Mode] fix: removing duplication

* [TS-Test-Mode] refactor: test.promise -> toastResultPromise

* Update src/renderer/routes/flow_chart/views/env-var/EnvVarModal.tsx

Co-authored-by: Jeff Zhang <[email protected]>

* [TS-Test-Mode] Removing Exposed shouldThrow from sequencer Handler

* Update src/renderer/routes/flow_chart/views/env-var/EnvVarModal.tsx

Co-authored-by: Jeff Zhang <[email protected]>

* [TS-Test-Mode] refactor: removing 'api' in window since always running within the electron context

* refactor: removing trhow args

* refactor(sequencerStore): direct access with useShallow

* refactor(sequencerStore): spliting UploadInfo in distinc field

* refactor(sequencerStore): removing some Immer state asignation + fix typo

* refactor(sequencerStore): splitting TestSequencerState in two: SequencerState <> SequencerTestState

* refactor(sequencerStore): renameing sequencer state: useDisplayedSequenceState <> useSequencerState

* chore: formatting

* [TS-Test-Mode] refactor(sequencerStore): atomic setter

* [TS-Test-Mode] refactor: removing modal provider

* [TS-Test-Mode] refactor: removing unused props input and return type in DND

* [TS-Test-Mode] refactor: handling abort, pause, resume in SequencerState

* [TS-Test-Mode] refactor(cloudPanl): Map<units> -> Record<units>

* [TS-Test-Mode] chore: removing console.log

* [TS-Test-Mode] chore: creating component for Global Status

* [TS-Test-Mode] Sidebar don't cover controlbar

* [TS-Test-Mode] refactor: removing state as arg when it's not a setter

* [TS-Test-Mode] refactor: using partition instead of two operation

* [TS-Test-Mode] fix: test to use async version of filePicker

* formatting

* fix: lint

* [TS-Test-Mode] fi:x text color on status

* [TS-Test-Mode] fix: checkout box

* chore: format

* chore: removing debug log

* [TS-Test-Mode] test: trying small delay to let the animaiton play before clicking

* [TS-Test-Mode] chore: playwright test, change Run Sequence selector to use a data-testid field

* [RemovingThrowFromSeqHandler] refactor: removing throw -> Using Result now

* [RemovingThrowFromSeqHandler] chore: rename var

* chore: formatting

* refactor: `new Err/Ok` -> `err/ok`

* [TS-Test-Mode] refactor: `toast.promise` => `toastResultPromise`

* [fix-unsafe-writeFile] fix: unsafe call to write file when using user input

* [TS-Test-Mode] refactor: remove dead code

* [TS-Test-Mode] fix: permission issue on toggleExport

* chore: formatting

---------

Co-authored-by: latentdream <[email protected]>
Co-authored-by: Jeff Zhang <[email protected]>
Co-authored-by: JeffDotPng <[email protected]>
  • Loading branch information
4 people authored Apr 9, 2024
1 parent 966284a commit 5102541
Show file tree
Hide file tree
Showing 87 changed files with 4,575 additions and 1,659 deletions.
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
import os
import logging
from flojoy import (
DataContainer,
flojoy,
get_env_var,
get_flojoy_cloud_url,
node_preflight,
DataFrame,
Boolean,
)
import flojoy_cloud
import pandas as pd

FLOJOY_CLOUD_URI: str = os.environ.get("FLOJOY_CLOUD_URI") or "https://cloud.flojoy.ai"


@node_preflight
def preflight():
Expand Down Expand Up @@ -48,7 +46,9 @@ def FLOJOY_CLOUD_DOWNLOAD(
"Flojoy Cloud key is not found! You can set it under Settings -> Environment Variables."
)

cloud = flojoy_cloud.FlojoyCloud(workspace_secret=api_key)
cloud = flojoy_cloud.FlojoyCloud(
workspace_secret=api_key, api_url=get_flojoy_cloud_url()
)

measurement = cloud.get_measurement(measurement_id)
logging.info(measurement)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import os
from flojoy.env_var import get_flojoy_cloud_url
import pandas as pd
from flojoy import (
DataContainer,
Expand Down Expand Up @@ -74,7 +75,9 @@ def FLOJOY_CLOUD_UPLOAD(

if default:
# Only upload if the data is not empty, otherwise pass through
cloud = flojoy_cloud.FlojoyCloud(workspace_secret=api_key)
cloud = flojoy_cloud.FlojoyCloud(
workspace_secret=api_key, api_url=get_flojoy_cloud_url()
)
data = None
# Optimist approach, assume that the data is at a castable dimension
if isinstance(default, DataFrame):
Expand Down
67 changes: 60 additions & 7 deletions captain/internal/manager.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import asyncio
import threading
import time

from queue import Queue
from typing import Any

from captain.internal.wsmanager import ConnectionManager
from captain.models.test_sequencer import MsgState
from captain.models.test_sequencer import MsgState, StatusTypes
from captain.models.topology import Topology
from captain.routes.cloud import utcnow_str
from captain.services.consumer.blocks_watcher import BlocksWatcher
from captain.types.test_sequence import TestSequenceMessage
from captain.types.worker import PoisonPill
Expand All @@ -22,31 +25,81 @@ def __init__(self):
# Manager for Test Sequencer activities
class TSManager(WSManager):
def __init__(self):
self.runner: asyncio.Runner | None = None # holds the running sequencer
# holds the running sequencer (only one at a time)
self.runner: asyncio.Runner | None = None
self.pause = False
self.poison_pill: PoisonPill | None = None
super().__init__()

def kill_runner(self, *args, **kwargs):
def new_runner(self, runner: asyncio.Runner):
if self.runner is not None:
self.kill_runner()
self.runner = runner
self.pause = False
self.poison_pill = None

def cleanup(self):
self.runner = None
self.pause = False

async def wait_if_paused(self, id_of_test_waiting_for_resume: str):
logger.info(f"Check if paused: {self.pause}")
if self.pause:
logger.info("Sending pause message")
await self.ws.broadcast(
TestSequenceMessage(
state=MsgState.paused.value,
target_id=id_of_test_waiting_for_resume,
status=StatusTypes.paused.value,
time_taken=-1,
created_at=utcnow_str(),
is_saved_to_cloud=False,
error=None,
)
)
while self.pause:
logger.info("Waiting for pause to be lifted")
if self.poison_pill is not None:
logger.info("Poison pill detected")
poison_pill = self.poison_pill
self.poison_pill = None
raise poison_pill
time.sleep(0.5)

def kill_runner(self):
if self.runner is not None:
logger.info("Killing TS Runner")
try:
self.poison_pill = PoisonPill()
self.runner.close()
except Exception as e:
# Current Task can't be kill, but a PoisonPill in queue will stop the next task
logger.error(f"Error while killing TS Runner: {e}")
except Exception:
# Current Task can't be kill, but this put a "Poison Pill" in queue will stop the next task
pass
self.runner = None
asyncio.run(
self.ws.broadcast(
TestSequenceMessage(
MsgState.error.value,
"",
False,
StatusTypes.aborted.value,
-1,
utcnow_str(),
False,
"Test sequence was interrupted",
)
)
)

def pause_runner(self):
if self.runner is not None:
logger.info("Pausing TS Runner")
self.pause = True

def resume_runner(self):
if self.pause:
logger.info("Resuming TS Runner")
self.pause = False


# Manager for flowchart activities (main manager)
class Manager(WSManager):
Expand Down
1 change: 1 addition & 0 deletions captain/models/pytest/pytest_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,4 @@ class Config:
class TestDiscoverContainer(BaseModel):
response: List[TestDiscoveryResponse]
missing_libraries: List[str] = Field(..., serialization_alias="missingLibraries")
error: Optional[str]
26 changes: 14 additions & 12 deletions captain/models/test_sequencer.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from enum import Enum
from enum import StrEnum
from typing import List, Literal, Optional, Union

from pydantic import BaseModel, Field
Expand All @@ -14,32 +14,36 @@ class LockedContextType(BaseModel):
is_locked: bool = Field(..., alias="isLocked")


class TestTypes(str, Enum):
class TestTypes(StrEnum):
pytest = "pytest"
python = "python"
flojoy = "flojoy"
matlab = "matlab"


class StatusTypes(str, Enum):
class StatusTypes(StrEnum):
pending = "pending"
running = "running"
paused = "paused"
pass_ = "pass"
failed = "failed"
fail = "fail"
aborted = "aborted"


class MsgState(str, Enum):
class MsgState(StrEnum):
test_set_start = "test_set_start"
test_set_export = "test_set_export"
running = "running"
test_done = "test_done"
error = "error"
paused = "paused"
test_set_done = "test_set_done"


class BackendMsg(BaseModel):
state: MsgState = Field(..., alias="state")
target_id: str = Field(..., alias="targetId")
result: bool = Field(..., alias="result")
status: str = Field(..., alias="status")
time_taken: float = Field(..., alias="timeTaken")
is_saved_to_cloud: bool = Field(..., alias="isSavedToCloud")
error: Optional[str] = Field(None, alias="error")
Expand All @@ -59,20 +63,20 @@ class Test(BaseModel):
export_to_cloud: bool = Field(..., alias="exportToCloud")


class Role(str, Enum):
class Role(StrEnum):
start = "start"
between = "between"
end = "end"


class ConditionalComponent(str, Enum):
class ConditionalComponent(StrEnum):
if_ = "if"
else_ = "else"
elif_ = "elif"
end = "end"


class ConditionalLeader(str, Enum):
class ConditionalLeader(StrEnum):
if_ = "if"


Expand Down Expand Up @@ -119,7 +123,7 @@ class TestDiscoverContainer(BaseModel):
response: List[TestDiscoveryResponse] = Field(..., alias="response")


TestSequenceEvents = Literal["run", "stop", "subscribe", "export"]
TestSequenceEvents = Literal["run", "stop", "subscribe", "pause", "resume"]


class TestData(BaseModel):
Expand All @@ -129,5 +133,3 @@ class TestData(BaseModel):
class TestSequenceRun(BaseModel):
event: TestSequenceEvents
data: Union[str, TestRootNode]
hardware_id: Union[str, None]
project_id: Union[str, None]
Loading

0 comments on commit 5102541

Please sign in to comment.