diff --git a/.github/workflows/cla.yml b/.github/workflows/cla.yml index b18f59d7..8556b36f 100644 --- a/.github/workflows/cla.yml +++ b/.github/workflows/cla.yml @@ -7,6 +7,9 @@ on: jobs: CLAssistant: + # Disabled for Hemi as CLA (Contributor License Agreement) is not required. + if: false + runs-on: ubuntu-latest steps: - name: "CLA Assistant" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2aee5eec..c1648773 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -3,7 +3,7 @@ name: "CI" # The workflow should be triggered on any push and release events. # Release events can push tags (triggering a push event). # Therefore: -# - docker-publish-staging – is only triggered on push events to main branch +# - docker-publish-staging – is only triggered on push events to hemi-main branch # - docker-publish-release – is only triggered on release events on: push: @@ -139,7 +139,7 @@ jobs: uses: coverallsapp/github-action@v2 docker-publish-staging: - if: (github.event_name == 'push' && github.ref == 'refs/heads/main') + if: (github.event_name == 'push' && github.ref == 'refs/heads/hemi-main') needs: [ flake8, isort, black, django-check ] runs-on: ubuntu-latest steps: @@ -161,8 +161,8 @@ jobs: - name: Login to DockerHub uses: docker/login-action@v3.2.0 with: - username: ${{ secrets.DOCKER_USER }} - password: ${{ secrets.DOCKER_PASSWORD }} + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Build and push id: docker_build uses: docker/build-push-action@v6.1.0 @@ -173,7 +173,7 @@ jobs: build-args: | BUILD_NUMBER=${{ env.BUILD_NUMBER }} VERSION=${{ github.ref_name }} - tags: safeglobal/safe-config-service:staging + tags: hemilabs/safe-config-service:staging cache-from: type=local,src=/tmp/.buildx-cache cache-to: type=local,dest=/tmp/.buildx-cache-new - # Temp fix @@ -209,8 +209,8 @@ jobs: - name: Login to DockerHub uses: docker/login-action@v3.2.0 with: - username: ${{ secrets.DOCKER_USER }} - password: ${{ secrets.DOCKER_PASSWORD }} + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Build and push id: docker_build uses: docker/build-push-action@v6.1.0 @@ -222,8 +222,8 @@ jobs: BUILD_NUMBER=${{ env.BUILD_NUMBER }} VERSION=${{ github.ref_name }} tags: | - safeglobal/safe-config-service:${{ github.event.release.tag_name }} - safeglobal/safe-config-service:latest + hemilabs/safe-config-service:${{ github.event.release.tag_name }} + hemilabs/safe-config-service:latest cache-from: type=local,src=/tmp/.buildx-cache cache-to: type=local,dest=/tmp/.buildx-cache-new - # Temp fix @@ -239,7 +239,8 @@ jobs: autodeploy: runs-on: ubuntu-latest needs: [docker-publish-staging] - if: github.event_name == 'push' && github.ref == 'refs/heads/main' + # Disabled for Hemi + if: false steps: - uses: actions/checkout@v4 - name: Deploy Staging diff --git a/src/chains/serializers.py b/src/chains/serializers.py index d7f28e35..d648df14 100644 --- a/src/chains/serializers.py +++ b/src/chains/serializers.py @@ -1,12 +1,15 @@ from abc import abstractmethod -from typing import Any +from typing import Any, Optional +from django.core.files.base import File from drf_yasg.utils import swagger_serializer_method from gnosis.eth.django.serializers import EthereumAddressField from rest_framework import serializers from rest_framework.exceptions import APIException from rest_framework.utils.serializer_helpers import ReturnDict +from config import settings + from .models import Chain, Feature, GasPrice, Wallet @@ -156,11 +159,39 @@ def to_representation(instance: Wallet) -> str: # type: ignore[override] return instance.key +class CustomImageField(serializers.ImageField): + """ + This class implements a custom serializer for the chain_logo_uri field. + + It is needed because the URIs are stored as relative paths but when + serializers.ImageField is called, those are transformed to absolute URLs by + picking the host from the request context. When the service is running as + part of a docker-compose set, the internal call in between services make the + serialized URL look like "http://nginx..." so the UI cannot find the logos. + """ + + def to_representation(self, value: Optional[File[Any]]) -> Optional[str]: + """ + Overrides the logic that transforms a relative to an absolute URL. + + If MEDIA_BASE_URL is set, it will be used instead of the request + context. Otherwise it will fallback to the default behavior. + """ + if not value: + return None + + base_url = settings.MEDIA_BASE_URL + if base_url and value.name: + return base_url.rstrip("/") + "/" + value.name + + return super().to_representation(value) + + class ChainSerializer(serializers.ModelSerializer[Chain]): chain_id = serializers.CharField(source="id") chain_name = serializers.CharField(source="name") short_name = serializers.CharField() - chain_logo_uri = serializers.ImageField(use_url=True) + chain_logo_uri = CustomImageField(use_url=True) rpc_uri = serializers.SerializerMethodField() safe_apps_rpc_uri = serializers.SerializerMethodField() public_rpc_uri = serializers.SerializerMethodField() diff --git a/src/config/settings.py b/src/config/settings.py index 1fbc4180..c97d44d2 100644 --- a/src/config/settings.py +++ b/src/config/settings.py @@ -213,6 +213,8 @@ MEDIA_ROOT = f"{BASE_DIR}/media/" # https://docs.djangoproject.com/en/dev/ref/settings/#media-url MEDIA_URL = os.getenv("MEDIA_URL", "/media/") +# This will override the base URL used to construct the media absolute URLs. +MEDIA_BASE_URL = os.getenv("MEDIA_BASE_URL", None) AWS_ACCESS_KEY_ID = os.getenv("AWS_ACCESS_KEY_ID") AWS_SECRET_ACCESS_KEY = os.getenv("AWS_SECRET_ACCESS_KEY")