From 32dad0efd833d0861aef9b23d61487dc6278fff7 Mon Sep 17 00:00:00 2001 From: Ihsan Ullah Date: Thu, 11 Jul 2024 19:38:00 +0500 Subject: [PATCH 01/27] autorun collectstatic when django container starts, added caddy_data and caddy_config to gitignore --- .gitignore | 3 +++ docker-compose.yml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 4ac22b2f4..2137ff1df 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,6 @@ server_config.yaml .DS_Store .DS_Store? + +caddy_config/ +caddy_data/ \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 2a213b2fe..b80180df5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -24,7 +24,7 @@ services: django: build: . # NOTE: We use watchmedo to reload gunicorn nicely, Uvicorn + Gunicorn reloads don't work well - command: bash -c "cd /app/src && watchmedo auto-restart -p '*.py' --recursive -- gunicorn asgi:application -w 2 -k uvicorn.workers.UvicornWorker -b :8000 -b :80 --capture-output --log-level debug" + command: bash -c "python manage.py collectstatic --noinput && cd /app/src && watchmedo auto-restart -p '*.py' --recursive -- gunicorn asgi:application -w 2 -k uvicorn.workers.UvicornWorker -b :8000 -b :80 --capture-output --log-level debug" environment: - DATABASE_URL=postgres://${DB_USERNAME}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_NAME} env_file: .env From 7d01068570effb91e4641e8239e8bcb2d9b75e9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20Pav=C3=A3o?= Date: Wed, 21 Aug 2024 01:07:18 -0300 Subject: [PATCH 02/27] Changed submission name to add ID when downloading many submissions (#1565) * changed submission name to add ID * Flake8 white space fix --------- Co-authored-by: Nicolas HOMBERG --- src/apps/api/views/submissions.py | 6 +++--- src/apps/competitions/tasks.py | 7 +------ 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/apps/api/views/submissions.py b/src/apps/api/views/submissions.py index 745cdb521..6c2489245 100644 --- a/src/apps/api/views/submissions.py +++ b/src/apps/api/views/submissions.py @@ -312,18 +312,18 @@ def re_run_many_submissions(self, request): submission.re_run() return Response({}) - # New methods impleted! @action(detail=False, methods=['get']) def download_many(self, request): pks = request.query_params.get('pks') if pks: pks = json.loads(pks) # Convert JSON string to list + # Doing a local import here to avoid circular imports from competitions.tasks import stream_batch_download - # Call the task and get the result (stream) + # in_memory_zip = stream_batch_download.apply_async((pks,)).get() in_memory_zip = stream_batch_download(pks) - # Stream the response + response = StreamingHttpResponse(in_memory_zip, content_type='application/zip') response['Content-Disposition'] = 'attachment; filename="bulk_submissions.zip"' return response diff --git a/src/apps/competitions/tasks.py b/src/apps/competitions/tasks.py index 1e5544b7b..f56696940 100644 --- a/src/apps/competitions/tasks.py +++ b/src/apps/competitions/tasks.py @@ -292,13 +292,10 @@ def retrieve_data(url, data=None): def zip_generator(submission_pks): in_memory_zip = BytesIO() - # logger.info("IN zip generator") with zipfile.ZipFile(in_memory_zip, 'w', zipfile.ZIP_DEFLATED) as zip_file: for submission_id in submission_pks: submission = Submission.objects.get(id=submission_id) - # logger.info(submission.data.data_file) - - short_name = submission.data.data_file.name.split('/')[-1] + short_name = "ID_" + str(submission_id) + '_' + submission.data.data_file.name.split('/')[-1] url = make_url_sassy(path=submission.data.data_file.name) for block in retrieve_data(url): zip_file.writestr(short_name, block) @@ -310,8 +307,6 @@ def zip_generator(submission_pks): @app.task(queue='site-worker', soft_time_limit=60 * 60) def stream_batch_download(submission_pks): - # logger.info("In stream_batch_download") - # logger.info(submission_pks) return zip_generator(submission_pks) From a37139a96d7f2beb169b40e9e322453545be5673 Mon Sep 17 00:00:00 2001 From: Ihsan Ullah Date: Wed, 21 Aug 2024 19:01:39 +0500 Subject: [PATCH 03/27] Server Status: submissions limit removed (#1562) * server status submissions limit removed, pagination added, monitor queues separated * renamed server status title to recent submissions --- src/apps/pages/urls.py | 1 + src/apps/pages/views.py | 29 +++++++++--- src/static/stylus/index.styl | 1 + src/static/stylus/server_status.styl | 19 ++++++++ src/templates/base.html | 1 + src/templates/pages/monitor_queues.html | 49 ++++++++++++++++++++ src/templates/pages/server_status.html | 61 +++++++++---------------- 7 files changed, 116 insertions(+), 45 deletions(-) create mode 100644 src/static/stylus/server_status.styl create mode 100644 src/templates/pages/monitor_queues.html diff --git a/src/apps/pages/urls.py b/src/apps/pages/urls.py index 084bd2c7e..bbba17d71 100644 --- a/src/apps/pages/urls.py +++ b/src/apps/pages/urls.py @@ -11,5 +11,6 @@ path('search', views.SearchView.as_view(), name="search"), path('organize', views.OrganizeView.as_view(), name="organize"), path('server_status', views.ServerStatusView.as_view(), name="server_status"), + path('monitor_queues', views.MonitorQueuesView.as_view(), name="monitor_queues"), # path('test', views.CompetitionListTestView.as_view()), ] diff --git a/src/apps/pages/views.py b/src/apps/pages/views.py index 4afa0c11d..0f21b8cf2 100644 --- a/src/apps/pages/views.py +++ b/src/apps/pages/views.py @@ -1,5 +1,4 @@ -from datetime import timedelta -from django.utils.timezone import now +from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage from django.views.generic import TemplateView from django.db.models import Count, Q @@ -55,6 +54,8 @@ class ServerStatusView(TemplateView): def get_context_data(self, *args, **kwargs): show_child_submissions = self.request.GET.get('show_child_submissions', False) + page = self.request.GET.get('page', 1) + submissions_per_page = 50 # Get all submissions qs = Submission.objects.all() @@ -73,9 +74,6 @@ def get_context_data(self, *args, **kwargs): else: qs = qs.none() # This returns an empty queryset - # Filter for fetching last 2 days submissions - qs = qs.filter(created_when__gte=now() - timedelta(days=2)) - # Filter out child submissions i.e. submission has no parent if not show_child_submissions: qs = qs.filter(parent__isnull=True) @@ -83,8 +81,20 @@ def get_context_data(self, *args, **kwargs): qs = qs.order_by('-created_when') qs = qs.select_related('phase__competition', 'owner') + # Paginate the queryset + paginator = Paginator(qs, submissions_per_page) + + try: + submissions = paginator.page(page) + except PageNotAnInteger: + # If page is not an integer, deliver the first page. + submissions = paginator.page(1) + except EmptyPage: + # If page is out of range, deliver last page of results. + submissions = paginator.page(paginator.num_pages) + context = super().get_context_data(*args, **kwargs) - context['submissions'] = qs[:250] + context['submissions'] = submissions context['show_child_submissions'] = show_child_submissions for submission in context['submissions']: @@ -103,6 +113,9 @@ def get_context_data(self, *args, **kwargs): # Add submission owner display name submission.owner_display_name = submission.owner.display_name if submission.owner.display_name else submission.owner.username + context['paginator'] = paginator + context['is_paginated'] = paginator.num_pages > 1 + return context def format_file_size(self, file_size): @@ -123,6 +136,10 @@ def format_file_size(self, file_size): return f"{n:.1f} {units[i]}" +class MonitorQueuesView(TemplateView): + template_name = 'pages/monitor_queues.html' + + def page_not_found_view(request, exception): print(request) return render(request, '404.html', status=404) diff --git a/src/static/stylus/index.styl b/src/static/stylus/index.styl index f68e56b2b..58cfc96bc 100644 --- a/src/static/stylus/index.styl +++ b/src/static/stylus/index.styl @@ -7,4 +7,5 @@ @import "src/static/stylus/simple_page.styl" @import "src/static/stylus/toastr.styl" @import "src/static/stylus/forum.styl" +@import "src/static/stylus/server_status.styl" diff --git a/src/static/stylus/server_status.styl b/src/static/stylus/server_status.styl new file mode 100644 index 000000000..2f96a3fe9 --- /dev/null +++ b/src/static/stylus/server_status.styl @@ -0,0 +1,19 @@ +.pagination-nav + padding 10px 0 + width 100% + margin-bottom 20px + display flex + justify-content center + align-items center + position relative + +.float-left + position absolute + left 0 + +.float-right + position absolute + right 0 + +.center + text-align center diff --git a/src/templates/base.html b/src/templates/base.html index de6296321..f6f650d5a 100644 --- a/src/templates/base.html +++ b/src/templates/base.html @@ -128,6 +128,7 @@ {# Customize Codalab#} Server Status {% if request.user.is_staff %} + Monitor Queues Django Admin Change User Analytics diff --git a/src/templates/pages/monitor_queues.html b/src/templates/pages/monitor_queues.html new file mode 100644 index 000000000..bcbf0c4c5 --- /dev/null +++ b/src/templates/pages/monitor_queues.html @@ -0,0 +1,49 @@ +{% extends "base.html" %} +{% load staticfiles %} + +{% block extra_head %} +{% endblock %} + +{% block content %} +
+

Monitor queues

+
+
+
+ + + +
+ RabbitMQ +
+ This page allows admins to view connections, queued messages, message rates, channels, + exchanges, and other administrative features relating to RabbitMQ e.g. Creating users, + adding v-hosts, and creating policies. +
+
+
+
+
+
+ + + +
+ Flower +
+ Flower is a powerful web-based Celery monitoring tool designed to keep track of our + tasks. + Admins may view the state of which tasks were run, with what arguments, and many more + features. Here you may also view which queues your celery workers are consuming, and the + state of any tasks in them. At last, there is also a great monitoring page for viewing + the + systemic impact of your workers. +
+
+
+
+
+
+ + +{% endblock %} diff --git a/src/templates/pages/server_status.html b/src/templates/pages/server_status.html index debf5ba1a..dde0138f1 100644 --- a/src/templates/pages/server_status.html +++ b/src/templates/pages/server_status.html @@ -6,7 +6,7 @@ {% block content %}
-

Recent submissions (up to 250 or 2 days old)

+

Recent Submissions

@@ -55,48 +55,31 @@

Recent submissions (up to 250 or 2 days old)

+ + {% if is_paginated %} +
+ {% if submissions.has_previous %} + + First + Previous + + {% endif %} + + + Page {{ submissions.number }} of {{ paginator.num_pages }} + + + + {% if submissions.has_next %} + + Next + Last + + {% endif %} - {% if user.is_superuser %} -

Monitor queues

-
-
-
- - - -
- RabbitMQ -
- This page allows admins to view connections, queued messages, message rates, channels, - exchanges, and other administrative features relating to RabbitMQ e.g. Creating users, - adding v-hosts, and creating policies. -
-
-
-
-
-
- - - -
- Flower -
- Flower is a powerful web-based Celery monitoring tool designed to keep track of our - tasks. - Admins may view the state of which tasks were run, with what arguments, and many more - features. Here you may also view which queues your celery workers are consuming, and the - state of any tasks in them. At last, there is also a great monitoring page for viewing - the - systemic impact of your workers. -
-
-
-
{% endif %}
- From 959d77666b2f01fbde3936e9546e27eacb0109a1 Mon Sep 17 00:00:00 2001 From: OhMaley Date: Mon, 16 Sep 2024 11:02:09 -0400 Subject: [PATCH 10/27] Fix string concat in case of no email in analytics api --- src/apps/api/views/analytics.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/apps/api/views/analytics.py b/src/apps/api/views/analytics.py index 922d0f438..0c056cd73 100644 --- a/src/apps/api/views/analytics.py +++ b/src/apps/api/views/analytics.py @@ -231,10 +231,12 @@ def competitions_usage(request): 'datefield' ) for su in query.order_by("-datefield", "competition__id"): + username = su['competition__created_by__username'] or ("user #" + su['competition__created_by__id']) or "unknown user" + email = su['competition__created_by__email'] or "no email" competitions_usage.setdefault(su['datefield'].isoformat(), {})[su['competition__id']] = { 'snapshot_id': su['id'], 'title': su['competition__title'], - 'organizer': su['competition__created_by__username'] + " (" + su['competition__created_by__email'] + ")", + 'organizer': username + " (" + email + ")", 'created_when': su['competition__created_when'], 'datasets': su['datasets_total'], } @@ -275,9 +277,11 @@ def users_usage(request): 'datefield' ) for su in query.order_by("-datefield", "user__id"): + username = su['user__username'] or ("user #" + su['user__id']) or "unknown user" + email = su['user__email'] or "no email" users_usage.setdefault(su['datefield'].isoformat(), {})[su['user__id']] = { 'snapshot_id': su['id'], - 'name': su['user__username'] + " (" + su['user__email'] + ")", + 'name': username + " (" + email + ")", 'date_joined': su['user__date_joined'], 'datasets': su['datasets_total'], 'submissions': su['submissions_total'], From 0b4f0a284454a21ebc59b9c0bb89701db2683e5c Mon Sep 17 00:00:00 2001 From: Obada Haddad-Soussac Date: Tue, 1 Oct 2024 18:20:14 +0200 Subject: [PATCH 11/27] Poetry error tentative fix (#1588) * Poetry error tentative fix * RabbitMQ static image in Dockerfile.rabbitmq to fix a recent bug * Reverted RabbitMQ image change * Fix Rabbit version --------- Co-authored-by: Obada Haddad Co-authored-by: didayolo --- Dockerfile | 2 +- Dockerfile.compute_worker | 2 +- Dockerfile.compute_worker_gpu | 2 +- Dockerfile.flower | 2 +- Dockerfile.rabbitmq | 2 +- pyproject.toml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Dockerfile b/Dockerfile index eed648e54..6368cef53 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,7 +5,7 @@ RUN apt-get update && apt-get install -y gcc build-essential && rm -rf /var/lib/ ENV PYTHONUNBUFFERED 1 -RUN curl -sSL https://install.python-poetry.org | python3 - +RUN curl -sSL https://install.python-poetry.org | python3 - --version 1.8.3 # Poetry location so future commands (below) work ENV PATH $PATH:/root/.local/bin # Want poetry to use system python of docker container diff --git a/Dockerfile.compute_worker b/Dockerfile.compute_worker index 7829899f9..6e6b626bf 100644 --- a/Dockerfile.compute_worker +++ b/Dockerfile.compute_worker @@ -7,7 +7,7 @@ ENV PYTHONUNBUFFERED 1 RUN apt-get update && curl -fsSL https://get.docker.com | sh -RUN curl -sSL https://install.python-poetry.org | python3 - +RUN curl -sSL https://install.python-poetry.org | python3 - --version 1.8.3 # Poetry location so future commands (below) work ENV PATH $PATH:/root/.local/bin # Want poetry to use system python of docker container diff --git a/Dockerfile.compute_worker_gpu b/Dockerfile.compute_worker_gpu index e4c2546fc..6bf96f3c5 100644 --- a/Dockerfile.compute_worker_gpu +++ b/Dockerfile.compute_worker_gpu @@ -19,7 +19,7 @@ RUN apt-get install -y nvidia-container-toolkit # BB - not convinced we need this ENV USE_GPU 1 -RUN curl -sSL https://install.python-poetry.org | python3 - +RUN curl -sSL https://install.python-poetry.org | python3 - --version 1.8.3 # Poetry location so future commands (below) work ENV PATH $PATH:/root/.local/bin # Want poetry to use system python of docker container diff --git a/Dockerfile.flower b/Dockerfile.flower index 59e84d6ed..30d482a8e 100644 --- a/Dockerfile.flower +++ b/Dockerfile.flower @@ -9,7 +9,7 @@ ENV PYTHONUNBUFFERED=1 PYTHONHASHSEED=random PYTHONDONTWRITEBYTECODE=1 RUN apt-get update && apt-get install -y ca-certificates && update-ca-certificates # # Install the required packages -RUN curl -sSL https://install.python-poetry.org | python3 - +RUN curl -sSL https://install.python-poetry.org | python3 - --version 1.8.3 # Poetry location so future commands (below) work ENV PATH $PATH:/root/.local/bin # Want poetry to use system python of docker container diff --git a/Dockerfile.rabbitmq b/Dockerfile.rabbitmq index fc0b411e8..106c81022 100644 --- a/Dockerfile.rabbitmq +++ b/Dockerfile.rabbitmq @@ -1,3 +1,3 @@ -FROM rabbitmq:management +FROM rabbitmq:3.13.7-management ARG WORKER_CONNECTION_TIMEOUT RUN echo "consumer_timeout = $WORKER_CONNECTION_TIMEOUT" >> /etc/rabbitmq/conf.d/10-defaults.conf diff --git a/pyproject.toml b/pyproject.toml index 39538b909..6a38ee991 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,7 @@ readme = "README.md" package-mode = false [tool.poetry.dependencies] -python = "3.9.19" +python = "3.9.20" django = "2.2.17" django-oauth-toolkit = "1.0.0" django-cors-middleware = "1.5.0" From 747acb28aff9945fcf686074238a6811a0818296 Mon Sep 17 00:00:00 2001 From: Ihsan Ullah Date: Wed, 2 Oct 2024 01:29:08 +0500 Subject: [PATCH 12/27] `Release PR#1` - Display release version in Codabench footer (#1583) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * release version added to header * version moved to footer * Minor UI change --------- Co-authored-by: Adrien Pavão --- src/static/stylus/base_template.styl | 13 +++++++++++++ src/templates/base.html | 3 ++- src/templates/pages/home.html | 2 +- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/static/stylus/base_template.styl b/src/static/stylus/base_template.styl index 53e3e7d8b..1545615e6 100644 --- a/src/static/stylus/base_template.styl +++ b/src/static/stylus/base_template.styl @@ -259,3 +259,16 @@ body.pushable>.pusher .modal max-height 90vh overflow-y scroll + +#version + margin-top 10px + text-align center + font-family monospace + font-size 12px + font-weight bold + padding 5px + color #8b8d8d + +#version a + text-decoration none + color inherit \ No newline at end of file diff --git a/src/templates/base.html b/src/templates/base.html index f6f650d5a..12ef41793 100644 --- a/src/templates/base.html +++ b/src/templates/base.html @@ -227,7 +227,8 @@

CodaBench

- + + {# Admin only user switching #} diff --git a/src/templates/pages/home.html b/src/templates/pages/home.html index 984c245b3..3316a58b5 100644 --- a/src/templates/pages/home.html +++ b/src/templates/pages/home.html @@ -7,7 +7,7 @@ {% block top_div_extra_content %} -
+
From 7ced144d5df70b110ea1a652ef6058ff503157ad Mon Sep 17 00:00:00 2001 From: Ihsan Ullah Date: Wed, 2 Oct 2024 01:51:28 +0500 Subject: [PATCH 13/27] `Release PR#2` Release version will load dynamically from version.json (#1592) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * release version added to header * version moved to footer * version on the website is now dynamic and will be loaded from the version.json file --------- Co-authored-by: Adrien Pavão --- src/templates/base.html | 6 +++++- src/utils/context_processors.py | 17 ++++++++++++++++- version.json | 7 +++++++ 3 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 version.json diff --git a/src/templates/base.html b/src/templates/base.html index 12ef41793..8b0271172 100644 --- a/src/templates/base.html +++ b/src/templates/base.html @@ -227,7 +227,11 @@

CodaBench

- + {% if VERSION_INFO.tag_name != 'invalid' and VERSION_INFO.tag_name != 'unknown' %} + + {% endif %} {# Admin only user switching #} diff --git a/src/utils/context_processors.py b/src/utils/context_processors.py index 9ed17f064..1c9787aa0 100644 --- a/src/utils/context_processors.py +++ b/src/utils/context_processors.py @@ -1,7 +1,11 @@ import json - +import os from django.conf import settings +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +# Set the absolute path for the version file +VERSION_FILE_PATH = os.path.join(os.path.dirname(BASE_DIR), 'version.json') + def common_settings(request): if request.user.is_authenticated: @@ -18,6 +22,16 @@ def common_settings(request): else: user_json_data = {"logged_in": False} + # Read version information from the version.json file + version_info = {} + try: + with open(VERSION_FILE_PATH) as version_file: + version_info = json.load(version_file) + except FileNotFoundError: + version_info = {"tag_name": "unknown"} + except json.JSONDecodeError: + version_info = {"tag_name": "invalid"} + return { 'STORAGE_TYPE': settings.STORAGE_TYPE, 'MAX_EXECUTION_TIME_LIMIT': settings.MAX_EXECUTION_TIME_LIMIT, @@ -26,4 +40,5 @@ def common_settings(request): 'FLOWER_URL': f"http://{settings.DOMAIN_NAME}:{settings.FLOWER_PUBLIC_PORT}", 'ENABLE_SIGN_UP': settings.ENABLE_SIGN_UP, 'ENABLE_SIGN_IN': settings.ENABLE_SIGN_IN, + 'VERSION_INFO': version_info, } diff --git a/version.json b/version.json new file mode 100644 index 000000000..0823df436 --- /dev/null +++ b/version.json @@ -0,0 +1,7 @@ +{ + "tag_name": "v1.11.0", + "release_name": "Release 1.11.0", + "published_at": "2024-09-16", + "body": "", + "release_url": "https://github.com/codalab/codabench/releases/tag/v1.11.0" +} \ No newline at end of file From de55ef3fc3642194d194fb79ab61aad6a3e25d6d Mon Sep 17 00:00:00 2001 From: Ihsan Ullah Date: Thu, 3 Oct 2024 19:10:21 +0500 Subject: [PATCH 14/27] `Release PR#3` created workflow for new releases (#1584) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * created workflow for new releases * version json file added * typo fix * Update release-version-update.yml * Included realease url to navigate user to the url on click on the website * release json updated --------- Co-authored-by: Obada Haddad Co-authored-by: Adrien Pavão --- .github/workflows/release-version-update.yml | 50 ++++++++++++++++++++ version.json | 10 ++-- 2 files changed, 55 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/release-version-update.yml diff --git a/.github/workflows/release-version-update.yml b/.github/workflows/release-version-update.yml new file mode 100644 index 000000000..c62158d1f --- /dev/null +++ b/.github/workflows/release-version-update.yml @@ -0,0 +1,50 @@ +name: Update version.json and create PR + +on: + release: + types: [published] + +jobs: + update-version: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Get release information + id: get_release + uses: dawidd6/action-get-latest-release@v3 + with: + release: true + + - name: Update version.json + run: | + echo '{ + "tag_name": "${{ steps.get_release.outputs.tag_name }}", + "release_name": "${{ steps.get_release.outputs.name }}", + "published_at": "${{ steps.get_release.outputs.published_at }}", + "body": "${{ steps.get_release.outputs.body }}" + "release_url": "${{ steps.get_release.outputs.html_url }}" + }' > version.json + + - name: Create new branch + run: | + git checkout -b update-version-${{ steps.get_release.outputs.tag_name }} + git add version.json + git commit -m "Update version.json for release ${{ steps.get_release.outputs.tag_name }}" + + - name: Push branch + run: | + git push origin update-version-${{ steps.get_release.outputs.tag_name }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Create Pull Request + uses: peter-evans/create-pull-request@v5 + with: + token: ${{ secrets.GITHUB_TOKEN }} + branch: update-version-${{ steps.get_release.outputs.tag_name }} + title: "Update version.json for release ${{ steps.get_release.outputs.tag_name }}" + body: "This PR updates version.json with the latest release information." + base: develop # Target branch for the pull request diff --git a/version.json b/version.json index 0823df436..6d0c65f69 100644 --- a/version.json +++ b/version.json @@ -1,7 +1,7 @@ { - "tag_name": "v1.11.0", - "release_name": "Release 1.11.0", - "published_at": "2024-09-16", - "body": "", - "release_url": "https://github.com/codalab/codabench/releases/tag/v1.11.0" + "tag_name": "v1.11.0", + "release_name": "Release 1.11.0", + "published_at": "2024-09-16", + "body": "", + "release_url": "https://github.com/codalab/codabench/releases/tag/v1.11.0" } \ No newline at end of file From 346bc535254c89b1576da0aa188be3d602a1fe6a Mon Sep 17 00:00:00 2001 From: Ihsan Ullah Date: Fri, 4 Oct 2024 14:18:52 +0500 Subject: [PATCH 15/27] resource interface-> task updates --- src/apps/api/serializers/tasks.py | 29 ++++++++++++++++--------- src/static/riot/tasks/management.tag | 32 +++++++++++++++++----------- 2 files changed, 38 insertions(+), 23 deletions(-) diff --git a/src/apps/api/serializers/tasks.py b/src/apps/api/serializers/tasks.py index acd07a8c4..35dcfe66a 100644 --- a/src/apps/api/serializers/tasks.py +++ b/src/apps/api/serializers/tasks.py @@ -99,6 +99,7 @@ class TaskDetailSerializer(WritableNestedModelSerializer): solutions = SolutionSerializer(many=True, required=False, read_only=True) validated = serializers.SerializerMethodField(required=False) shared_with = serializers.SerializerMethodField() + competitions = serializers.SerializerMethodField() class Meta: model = Task @@ -112,6 +113,8 @@ class Meta: 'created_when', 'is_public', 'validated', + 'shared_with', + 'competitions', # Data pieces 'input_data', @@ -119,9 +122,16 @@ class Meta: 'reference_data', 'scoring_program', 'solutions', - 'shared_with', ) + def get_competitions(self, instance): + + # Fech competitions which hase phases with this task + # competitions = Phase.objects.filter(tasks__in=[instance.pk]).values('competition') + competitions = Competition.objects.filter(phases__tasks__in=[instance.pk]).values("id", "title").distinct() + + return competitions + def get_validated(self, task): return task.validated is not None @@ -136,10 +146,9 @@ def get_owner_display_name(self, instance): class TaskListSerializer(serializers.ModelSerializer): solutions = SolutionListSerializer(many=True, required=False, read_only=True) value = serializers.CharField(source='key', required=False) - competitions = serializers.SerializerMethodField() - shared_with = serializers.SerializerMethodField() created_by = serializers.CharField(source='created_by.username', read_only=True) owner_display_name = serializers.SerializerMethodField() + is_used_in_competitions = serializers.SerializerMethodField() class Meta: model = Task @@ -150,21 +159,21 @@ class Meta: 'owner_display_name', 'key', 'name', + 'description', 'solutions', 'ingestion_only_during_scoring', # Value is used for Semantic Multiselect dropdown api calls 'value', - 'competitions', - 'shared_with', + 'is_public', + 'is_used_in_competitions', ) - def get_competitions(self, instance): + def get_is_used_in_competitions(self, instance): - # Fech competitions which hase phases with this task - # competitions = Phase.objects.filter(tasks__in=[instance.pk]).values('competition') - competitions = Competition.objects.filter(phases__tasks__in=[instance.pk]).values("id", "title").distinct() + # Count competitions that are using this task + num_competitions = Competition.objects.filter(phases__tasks__in=[instance.pk]).distinct().count() - return competitions + return num_competitions > 0 def get_shared_with(self, instance): return self.context['shared_with'][instance.pk] diff --git a/src/static/riot/tasks/management.tag b/src/static/riot/tasks/management.tag index 37510275e..93d2a65bb 100644 --- a/src/static/riot/tasks/management.tag +++ b/src/static/riot/tasks/management.tag @@ -19,9 +19,9 @@ Name - Benchmarks - Shared With - Uploaded... + Description + Creator + In Use Public Actions @@ -30,17 +30,11 @@ { task.name } - -
- -
- - + { task.description } + {task.owner_display_name} + + - { task.shared_with.join(', ') } - { timeSince(Date.parse(task.created_when)) } ago @@ -88,6 +82,7 @@ +