From 3d068b3be6555f08b20abfdebad3bd253505f5d7 Mon Sep 17 00:00:00 2001 From: Duncan Ragsdale <88173870+Thistleman@users.noreply.github.com> Date: Thu, 25 Jul 2024 15:35:56 -0700 Subject: [PATCH 01/11] FE image adjustments and quick dev test Signed-off-by: Duncan Ragsdale <88173870+Thistleman@users.noreply.github.com> --- ec2/config.json | 2 +- pv-validation-hub-client | 2 +- .../evaluation_scripts/1/config.json | 49 ------ .../evaluation_scripts/1/file_test_link.csv | 144 ------------------ 4 files changed, 2 insertions(+), 195 deletions(-) delete mode 100644 s3Emulator/pv-validation-hub-bucket/evaluation_scripts/1/config.json delete mode 100644 s3Emulator/pv-validation-hub-bucket/evaluation_scripts/1/file_test_link.csv diff --git a/ec2/config.json b/ec2/config.json index 6a3d09f4..aba21fcf 100755 --- a/ec2/config.json +++ b/ec2/config.json @@ -1,5 +1,5 @@ { - "category_name": "Time Shift Analysis", + "category_name": "Quick Dev TS", "function_name": "detect_time_shifts", "comparison_type": "time_series", "performance_metrics": [ diff --git a/pv-validation-hub-client b/pv-validation-hub-client index 0e979534..727635f8 160000 --- a/pv-validation-hub-client +++ b/pv-validation-hub-client @@ -1 +1 @@ -Subproject commit 0e979534d4446c6464c24131ddfa37c0eb692a8f +Subproject commit 727635f86fd40fc28d71b4c5e42db255d32c5419 diff --git a/s3Emulator/pv-validation-hub-bucket/evaluation_scripts/1/config.json b/s3Emulator/pv-validation-hub-bucket/evaluation_scripts/1/config.json deleted file mode 100644 index 6a3d09f4..00000000 --- a/s3Emulator/pv-validation-hub-bucket/evaluation_scripts/1/config.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "category_name": "Time Shift Analysis", - "function_name": "detect_time_shifts", - "comparison_type": "time_series", - "performance_metrics": [ - "runtime", - "mean_absolute_error" - ], - "allowable_kwargs": [ - "latitude", - "longitude", - "data_sampling_frequency" - ], - "ground_truth_compare": [ - "time_series" - ], - "public_results_table": "time-shift-public-metrics.json", - "private_results_columns": [ - "system_id", - "file_name", - "run_time", - "data_requirements", - "mean_absolute_error_time_series", - "data_sampling_frequency", - "issue" - ], - "plots": [ - { - "type": "histogram", - "x_val": "mean_absolute_error_time_series", - "color_code": "issue", - "title": "Time Series MAE Distribution by Issue", - "save_file_path": "mean_absolute_error_time_series_dist.png" - }, - { - "type": "histogram", - "x_val": "mean_absolute_error_time_series", - "color_code": "data_sampling_frequency", - "title": "Time Series MAE Distribution by Sampling Frequency", - "save_file_path": "mean_absolute_error_time_series_dist.png" - }, - { - "type": "histogram", - "x_val": "run_time", - "title": "Run Time Distribution", - "save_file_path": "run_time_dist.png" - } - ] -} \ No newline at end of file diff --git a/s3Emulator/pv-validation-hub-bucket/evaluation_scripts/1/file_test_link.csv b/s3Emulator/pv-validation-hub-bucket/evaluation_scripts/1/file_test_link.csv deleted file mode 100644 index 14497e0f..00000000 --- a/s3Emulator/pv-validation-hub-bucket/evaluation_scripts/1/file_test_link.csv +++ /dev/null @@ -1,144 +0,0 @@ -test_id,file_id -0,1 -1,2 -2,3 -3,4 -4,5 -5,6 -6,7 -7,8 -8,9 -9,10 -10,11 -11,12 -12,13 -13,14 -14,15 -15,16 -16,17 -17,18 -18,19 -19,20 -20,21 -21,22 -22,23 -23,24 -24,25 -25,26 -26,27 -27,28 -28,29 -29,30 -30,31 -31,32 -32,33 -33,34 -34,35 -35,36 -36,37 -37,38 -38,39 -39,40 -40,41 -41,42 -42,43 -43,44 -44,45 -45,46 -46,47 -47,48 -48,49 -49,50 -50,51 -51,52 -52,53 -53,54 -54,55 -55,56 -56,57 -57,58 -58,59 -59,60 -60,61 -61,62 -62,63 -63,64 -64,65 -65,66 -66,67 -67,68 -68,69 -69,70 -70,71 -71,72 -72,73 -73,74 -74,75 -75,76 -76,77 -77,78 -78,79 -79,80 -80,81 -81,82 -82,83 -83,84 -84,85 -85,86 -86,87 -87,88 -88,89 -89,90 -90,91 -91,92 -92,93 -93,94 -94,95 -95,96 -96,97 -97,98 -98,99 -99,100 -100,101 -101,102 -102,103 -103,104 -104,105 -105,106 -106,107 -107,108 -108,109 -109,110 -110,111 -111,112 -112,113 -113,114 -114,115 -115,116 -116,117 -117,118 -118,119 -119,120 -120,121 -121,122 -122,123 -123,124 -124,125 -125,126 -126,127 -127,128 -128,129 -129,130 -130,131 -131,132 -132,133 -133,134 -134,135 -135,136 -136,137 -137,138 -138,139 -139,140 -140,141 -141,142 -142,143 From 963a2de45d9d1ede15988511ed51dffef04468aa Mon Sep 17 00:00:00 2001 From: Duncan Ragsdale <88173870+Thistleman@users.noreply.github.com> Date: Fri, 26 Jul 2024 12:48:06 -0700 Subject: [PATCH 02/11] integrate FE changes Signed-off-by: Duncan Ragsdale <88173870+Thistleman@users.noreply.github.com> --- pv-validation-hub-client | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pv-validation-hub-client b/pv-validation-hub-client index 727635f8..48375cb3 160000 --- a/pv-validation-hub-client +++ b/pv-validation-hub-client @@ -1 +1 @@ -Subproject commit 727635f86fd40fc28d71b4c5e42db255d32c5419 +Subproject commit 48375cb3b1e3834e1a3dde9167f075185d0c9ac4 From e868a82b5710b053fe75e178c1e3fe4644d0f90d Mon Sep 17 00:00:00 2001 From: Mitchell Victoriano Date: Fri, 26 Jul 2024 13:16:37 -0700 Subject: [PATCH 03/11] Added local api access to worker through credentials --- workers/src/utility.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/workers/src/utility.py b/workers/src/utility.py index a9212c39..83a60c18 100644 --- a/workers/src/utility.py +++ b/workers/src/utility.py @@ -603,7 +603,11 @@ def get_login_secrets_from_aws() -> tuple[str, str]: def with_credentials(logger: Logger | None = None): - username, password = get_login_secrets_from_aws() + if IS_LOCAL: + username = os.environ.get("admin_username", None) + password = os.environ.get("admin_password", None) + else: + username, password = get_login_secrets_from_aws() if not username or not password: raise Exception("Missing admin credentials") From 1846c0f51ee5d2937a42ca40f4e38a5f473650dd Mon Sep 17 00:00:00 2001 From: Duncan Ragsdale <88173870+Thistleman@users.noreply.github.com> Date: Fri, 26 Jul 2024 13:16:47 -0700 Subject: [PATCH 04/11] added missing env variables Signed-off-by: Duncan Ragsdale <88173870+Thistleman@users.noreply.github.com> --- .env.example | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.env.example b/.env.example index 2d253a73..3882cc20 100644 --- a/.env.example +++ b/.env.example @@ -1,3 +1,8 @@ djangosk=django-insecure-y&pp1if&0y)pxtmqf_@o1br(&-6mrxv**f5%&73d@d51kscvg! POSTGRES_PASSWORD=valhub -POSTGRES_USER=valhub \ No newline at end of file +POSTGRES_USER=valhub +admin_username=admin +admin_password=admin +admin_email=admin@admin.com +DOCKER_HOST_VOLUME_DATA_DIR="//workers/current_evaluation/data" +DOCKER_HOST_VOLUME_RESULTS_DIR="//workers/current_evaluation/results" \ No newline at end of file From 2d27fe509aa7538a61df59d96980d309bbe25b02 Mon Sep 17 00:00:00 2001 From: Mitchell Victoriano Date: Fri, 26 Jul 2024 13:17:49 -0700 Subject: [PATCH 05/11] Added change to docker compose to remove aws bind volume --- docker-compose.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 08a3e7aa..69479d3f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -129,9 +129,9 @@ services: - ./workers/tmp:/tmp - ./workers/requirements.txt:/root/worker/requirements.txt - ./workers/src:/root/worker/src - - type: bind - source: ~/.aws - target: /root/.aws + # - type: bind + # source: ~/.aws + # target: /root/.aws restart: unless-stopped develop: watch: From 26a15044e9c2e45fe78f80b0ef1fe4a9bac30ade Mon Sep 17 00:00:00 2001 From: Mitchell Victoriano Date: Fri, 26 Jul 2024 13:54:44 -0700 Subject: [PATCH 06/11] Added try catch to docker build --- workers/src/utility.py | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/workers/src/utility.py b/workers/src/utility.py index 83a60c18..adc8f489 100644 --- a/workers/src/utility.py +++ b/workers/src/utility.py @@ -5,7 +5,7 @@ from dask import config import docker from docker.models.containers import Container -from docker.errors import ImageNotFound +from docker.errors import ImageNotFound, BuildError from docker.models.images import Image from concurrent.futures import ( @@ -1033,21 +1033,28 @@ def create_docker_image( else: logger_if_able("Docker image does not exist") - # Create docker image from Dockerfile - image, build_logs = client.images.build( - path=dir_path, - tag=tag, - rm=True, - dockerfile="Dockerfile", - buildargs={"zip_file": f"{submission_file_name}"}, - ) - for log in build_logs: - if "stream" in log: - logger_if_able(log["stream"].strip()) + try: + # Create docker image from Dockerfile + image, build_logs = client.images.build( + path=dir_path, + tag=tag, + rm=True, + dockerfile="Dockerfile", + buildargs={"zip_file": f"{submission_file_name}"}, + ) + for log in build_logs: + if "stream" in log: + logger_if_able(log["stream"].strip()) - logger_if_able("Docker image created") + logger_if_able("Docker image created") - return image + return image + except BuildError as e: + logger_if_able(f"Error: {e}", logger, "ERROR") + raise e + except Exception as e: + logger_if_able(f"Error: {e}", logger, "ERROR") + raise e class DockerClientContextManager: From 2719d3355a29e2ab8d21a93423bfae9f165cb042 Mon Sep 17 00:00:00 2001 From: Mitchell Victoriano Date: Fri, 26 Jul 2024 14:44:19 -0700 Subject: [PATCH 07/11] Testing lower level api to see if build prints logs --- workers/src/utility.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/workers/src/utility.py b/workers/src/utility.py index adc8f489..b54c8edf 100644 --- a/workers/src/utility.py +++ b/workers/src/utility.py @@ -1031,23 +1031,34 @@ def create_docker_image( logger_if_able(image, logger) return image else: - logger_if_able("Docker image does not exist") + logger_if_able("Docker image does not exist", logger) + logger_if_able("Creating Docker image", logger) try: # Create docker image from Dockerfile - image, build_logs = client.images.build( + live_log_generator = client.api.build( path=dir_path, tag=tag, rm=True, dockerfile="Dockerfile", buildargs={"zip_file": f"{submission_file_name}"}, ) - for log in build_logs: - if "stream" in log: - logger_if_able(log["stream"].strip()) + for line in live_log_generator: + line_dict = json.loads(line) + if line_dict.get("stream"): + logger_if_able( + line_dict["stream"].rstrip(), logger, "INFO" + ) logger_if_able("Docker image created") + try: + image = client.images.get(tag) + except ImageNotFound: + logger_if_able("Docker image not found", logger) + except Exception as e: + raise e + return image except BuildError as e: logger_if_able(f"Error: {e}", logger, "ERROR") From 18e58b266ea56cccbdddc08e4f7429686a2c1d83 Mon Sep 17 00:00:00 2001 From: Duncan Ragsdale <88173870+Thistleman@users.noreply.github.com> Date: Mon, 29 Jul 2024 13:01:26 -0700 Subject: [PATCH 08/11] fixed subcontainer build dependencies Signed-off-by: Duncan Ragsdale <88173870+Thistleman@users.noreply.github.com> --- workers/src/docker/Dockerfile | 10 ++++++++-- workers/src/docker/submission/requirements.txt | 2 ++ workers/src/docker/submission/submission_wrapper.py | 10 ++++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 workers/src/docker/submission/requirements.txt create mode 100644 workers/src/docker/submission/submission_wrapper.py diff --git a/workers/src/docker/Dockerfile b/workers/src/docker/Dockerfile index 2ffc153c..c6b533ee 100644 --- a/workers/src/docker/Dockerfile +++ b/workers/src/docker/Dockerfile @@ -4,7 +4,13 @@ FROM python:3.11-slim # Set the working directory in the container WORKDIR /app -RUN apt-get update +RUN apt-get update && apt-get install -y \ + build-essential \ + libopenblas-dev \ + libhdf5-dev \ + python3-dev \ + cmake \ + pkg-config COPY unzip.py . COPY requirements.txt . @@ -24,7 +30,7 @@ RUN python -m unzip $zip_file submission WORKDIR /app/submission # Install the Python dependencies -RUN pip install --no-cache-dir -r requirements.txt +RUN pip install -r requirements.txt # Set the working directory in the container diff --git a/workers/src/docker/submission/requirements.txt b/workers/src/docker/submission/requirements.txt new file mode 100644 index 00000000..ede8c739 --- /dev/null +++ b/workers/src/docker/submission/requirements.txt @@ -0,0 +1,2 @@ +numpy +solar-data-tools diff --git a/workers/src/docker/submission/submission_wrapper.py b/workers/src/docker/submission/submission_wrapper.py new file mode 100644 index 00000000..78112f51 --- /dev/null +++ b/workers/src/docker/submission/submission_wrapper.py @@ -0,0 +1,10 @@ +import numpy as np +from solardatatools import DataHandler + + +def detect_time_shifts( + time_series, latitude=None, longitude=None, data_sampling_frequency=None +): + dh = DataHandler(time_series.to_frame()) + dh.run_pipeline(fix_shifts=True, verbose=False, round_shifts_to_hour=False) + return dh.time_shift_analysis.correction_estimate From 0bd115c89bc7218d17a6d133b9a33a4ac03f72aa Mon Sep 17 00:00:00 2001 From: Duncan Ragsdale <88173870+Thistleman@users.noreply.github.com> Date: Tue, 30 Jul 2024 16:22:12 -0700 Subject: [PATCH 09/11] bug fixes for submission data passthrough and docker build, added base resource page frame Signed-off-by: Duncan Ragsdale <88173870+Thistleman@users.noreply.github.com> --- .../migrations/0008_auto_20240730_1750.py | 28 +++++++++++ valhub/submissions/models.py | 5 +- valhub/submissions/serializers.py | 49 ++++++++++++------- valhub/submissions/views.py | 17 ++++++- .../0002_alter_systemmetadata_dc_capacity.py | 18 +++++++ workers/src/pvinsight-validation-runner.py | 31 +++--------- workers/src/utility.py | 13 +++-- 7 files changed, 113 insertions(+), 48 deletions(-) create mode 100644 valhub/submissions/migrations/0008_auto_20240730_1750.py create mode 100644 valhub/system_metadata/migrations/0002_alter_systemmetadata_dc_capacity.py diff --git a/valhub/submissions/migrations/0008_auto_20240730_1750.py b/valhub/submissions/migrations/0008_auto_20240730_1750.py new file mode 100644 index 00000000..b794440b --- /dev/null +++ b/valhub/submissions/migrations/0008_auto_20240730_1750.py @@ -0,0 +1,28 @@ +# Generated by Django 3.2.16 on 2024-07-30 17:50 + +import django.contrib.postgres.fields +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("submissions", "0007_alter_submission_result"), + ] + + operations = [ + migrations.RemoveField( + model_name="submission", + name="mae", + ), + migrations.AlterField( + model_name="submission", + name="data_requirements", + field=django.contrib.postgres.fields.ArrayField( + base_field=models.CharField(max_length=100), + blank=True, + default=list, + size=None, + ), + ), + ] diff --git a/valhub/submissions/models.py b/valhub/submissions/models.py index e8c41f0c..f157b2bf 100644 --- a/valhub/submissions/models.py +++ b/valhub/submissions/models.py @@ -1,4 +1,5 @@ from django.db import models +from django.contrib.postgres.fields import ArrayField from analyses.models import Analysis from base.utils import RandomFileName @@ -47,7 +48,9 @@ class Submission(models.Model): alt_name = models.TextField(null=True, blank=True, default="") # mrt - mean run time mrt = models.FloatField(null=True, blank=True) - data_requirements = models.TextField(null=True, blank=True) + data_requirements = ArrayField( + models.CharField(max_length=100), blank=True, default=list + ) archived = models.BooleanField(default=False) python_version = models.DecimalField( max_digits=4, diff --git a/valhub/submissions/serializers.py b/valhub/submissions/serializers.py index 814b8ed3..78414992 100644 --- a/valhub/submissions/serializers.py +++ b/valhub/submissions/serializers.py @@ -135,22 +135,35 @@ def to_representation(self, instance): "username": instance.created_by.username, } - # Attempt to load the stringified array from the text field - try: - data_requirements = json.loads(instance.data_requirements) - # Ensure that the loaded object is a list - if not isinstance(data_requirements, list): - raise ValueError( - "Loaded object is not a list" - ) # Include a message with the ValueError - except (ValueError, TypeError) as e: - logger.error( - f"Failed to parse data_requirements for submission {instance.submission_id}: {e}" - ) - logger.error(f"With a value of {instance.data_requirements}") - data_requirements = ( - [] - ) # Default to an empty list if any error occurs - - data["data_requirements"] = data_requirements + return data + + +class SubmissionPrivateReportSerializer(serializers.ModelSerializer): + """ + Serialize the private report of Submission Model. + """ + + class Meta: + model = Submission + fields = ( + "submission_id", + "result", + "mrt", + "data_requirements", + "submitted_at", + "alt_name", + "archived", + "python_version", + "worker_version", + ) + + def to_representation(self, instance): + data = super( + SubmissionPrivateReportSerializer, self + ).to_representation(instance) + data["created_by"] = { + "uuid": instance.created_by.uuid, + "username": instance.created_by.username, + } + return data diff --git a/valhub/submissions/views.py b/valhub/submissions/views.py index fb22f390..c0952bd1 100644 --- a/valhub/submissions/views.py +++ b/valhub/submissions/views.py @@ -33,7 +33,11 @@ from .models import Submission from urllib.parse import urljoin -from .serializers import SubmissionSerializer, SubmissionDetailSerializer +from .serializers import ( + SubmissionSerializer, + SubmissionDetailSerializer, + SubmissionPrivateReportSerializer, +) from .models import Submission @@ -273,6 +277,11 @@ def update_submission_result(request: Request, submission_id: str): response_data = {"error": f"{field} is required"} return Response(response_data, status=status.HTTP_400_BAD_REQUEST) + # Validate that function_parameters is a list + if not isinstance(results["function_parameters"], list): + response_data = {"error": "function_parameters must be a list"} + return Response(response_data, status=status.HTTP_400_BAD_REQUEST) + logging.info(f"results = {results}") submission.mrt = float(results["mean_run_time"]) submission.data_requirements = results["function_parameters"] @@ -375,6 +384,9 @@ def leaderboard_update(request: Request): submission.mrt = float(mrt) if data_requirements is not None: + if isinstance(data_requirements, str): + # Convert the string to a list of strings + data_requirements = [data_requirements] submission.data_requirements = data_requirements submission.save() @@ -543,6 +555,9 @@ def get_submission_results(request: Request, submission_id: str): # set returns logging.info(f"setting returns") ret["marimo_url"] = file_urls + ret["submission_details"] = SubmissionPrivateReportSerializer( + submission + ).data return JsonResponse(ret, status=status.HTTP_200_OK) diff --git a/valhub/system_metadata/migrations/0002_alter_systemmetadata_dc_capacity.py b/valhub/system_metadata/migrations/0002_alter_systemmetadata_dc_capacity.py new file mode 100644 index 00000000..f69bb3de --- /dev/null +++ b/valhub/system_metadata/migrations/0002_alter_systemmetadata_dc_capacity.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.16 on 2024-07-30 17:50 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("system_metadata", "0001_initial"), + ] + + operations = [ + migrations.AlterField( + model_name="systemmetadata", + name="dc_capacity", + field=models.FloatField(default=0.0), + ), + ] diff --git a/workers/src/pvinsight-validation-runner.py b/workers/src/pvinsight-validation-runner.py index e08ffc63..34b0665c 100644 --- a/workers/src/pvinsight-validation-runner.py +++ b/workers/src/pvinsight-validation-runner.py @@ -564,7 +564,7 @@ def run( # noqa: C901 "data_requirements" ].iloc[0] - metrics_list = [] + metrics_dict = {} # Get the mean and median absolute errors # when combining the metric and name for the public metrics dictionary, @@ -582,22 +582,10 @@ def run( # noqa: C901 mean_metric = results_df[metric_name].mean() - public_metrics_dict["mean_" + metric] = mean_metric - - metric_tuple = ( - f"mean_{metric}", - mean_metric, - ) - metrics_list.append(metric_tuple) + metrics_dict[f"mean_{metric}"] = mean_metric median_metric = results_df[metric_name].median() - public_metrics_dict["median_" + metric] = median_metric - - metric_tuple = ( - f"median_{metric}", - median_metric, - ) - metrics_list.append(metric_tuple) + metrics_dict[f"median_{metric}"] = median_metric elif "runtime" in metric: key = "run_time" @@ -606,13 +594,10 @@ def run( # noqa: C901 mean_metric = results_df[key].mean() - metric_tuple = ( - f"mean_{key}", - mean_metric, - ) - metrics_list.append(metric_tuple) + metrics_dict[f"mean_{key}"] = mean_metric - public_metrics_dict["metrics"] = json.dumps(metrics_list) + # json dump no longer needed, as using json field in database + public_metrics_dict["metrics"] = metrics_dict # Write public metric information to a public results table. with open( @@ -1184,8 +1169,8 @@ def generate_performance_metrics_for_submission( results_dictionary["file_name"] = file_name # Set the runtime in the results dictionary results_dictionary["run_time"] = submission_runtime - # Set the data requirements in the dictionary, JSON required or bad juju happens in my DB and FE - results_dictionary["data_requirements"] = json.dumps(function_parameters) + # Set the data requirements in the dictionary, must be a list for DB array field + results_dictionary["data_requirements"] = function_parameters # Loop through the rest of the performance metrics and calculate them # (this predominantly applies to error metrics) for metric in performance_metrics: diff --git a/workers/src/utility.py b/workers/src/utility.py index b54c8edf..c2b8200d 100644 --- a/workers/src/utility.py +++ b/workers/src/utility.py @@ -1044,11 +1044,14 @@ def create_docker_image( buildargs={"zip_file": f"{submission_file_name}"}, ) for line in live_log_generator: - line_dict = json.loads(line) - if line_dict.get("stream"): - logger_if_able( - line_dict["stream"].rstrip(), logger, "INFO" - ) + try: + line_dict = json.loads(line) + if line_dict.get("stream"): + logger_if_able( + line_dict["stream"].rstrip(), logger, "INFO" + ) + except json.JSONDecodeError: + logger_if_able(line, logger, "INFO") logger_if_able("Docker image created") From a11d25a70641ab195fff3ce1bc54fcaddd6bf85d Mon Sep 17 00:00:00 2001 From: Duncan Ragsdale <88173870+Thistleman@users.noreply.github.com> Date: Tue, 30 Jul 2024 16:24:07 -0700 Subject: [PATCH 10/11] updated client Signed-off-by: Duncan Ragsdale <88173870+Thistleman@users.noreply.github.com> --- pv-validation-hub-client | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pv-validation-hub-client b/pv-validation-hub-client index 48375cb3..dda80fe6 160000 --- a/pv-validation-hub-client +++ b/pv-validation-hub-client @@ -1 +1 @@ -Subproject commit 48375cb3b1e3834e1a3dde9167f075185d0c9ac4 +Subproject commit dda80fe68ed08466ac7df78c4a71246fa5202df1 From 0d09e9a5777486c5e676acc54332de1e037edb10 Mon Sep 17 00:00:00 2001 From: Duncan Ragsdale <88173870+Thistleman@users.noreply.github.com> Date: Thu, 1 Aug 2024 10:04:23 -0700 Subject: [PATCH 11/11] front-end resource page cleanup Signed-off-by: Duncan Ragsdale <88173870+Thistleman@users.noreply.github.com> --- pv-validation-hub-client | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pv-validation-hub-client b/pv-validation-hub-client index dda80fe6..c144e18d 160000 --- a/pv-validation-hub-client +++ b/pv-validation-hub-client @@ -1 +1 @@ -Subproject commit dda80fe68ed08466ac7df78c4a71246fa5202df1 +Subproject commit c144e18d982ed4274dc990512d4ad5e902b65a09