mirror of
https://github.com/Screenly/Anthias.git
synced 2026-06-10 09:08:09 -04:00
Merge remote-tracking branch 'origin/master' into zmq-redis-pubsub-1
# Conflicts: # viewer/__init__.py
This commit is contained in:
78
.github/workflows/docker-build.yaml
vendored
78
.github/workflows/docker-build.yaml
vendored
@@ -37,6 +37,15 @@ jobs:
|
||||
|
||||
buildx:
|
||||
needs: run-tests
|
||||
# Scoped per-job (not at workflow level) so `run-tests` and any
|
||||
# future read-only job don't inherit `packages: write`. `buildx`
|
||||
# needs it so `docker login ghcr.io` with GITHUB_TOKEN can push
|
||||
# ghcr.io/screenly/anthias-*. `contents: read` is the implicit
|
||||
# default but pinned explicitly so a future workflow edit can't
|
||||
# silently lose checkout access.
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
strategy:
|
||||
# Don't cancel sibling jobs on the first failure: any platform that
|
||||
# has already finished building its image will have pushed the
|
||||
@@ -106,6 +115,14 @@ jobs:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
if: success() && github.event_name == 'push'
|
||||
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build Container
|
||||
env:
|
||||
DOCKER_BUILDKIT: 1
|
||||
@@ -132,13 +149,31 @@ jobs:
|
||||
# checks every <short-hash>-<board> tag is resolvable before any
|
||||
# retag fires, so a missing source tag fails the job before it
|
||||
# mutates the registry. `imagetools create` re-points the registry
|
||||
# tag to the existing manifest without re-uploading layers, so the
|
||||
# full ~98 retags (7 boards × 7 services × 2 namespaces) finish in
|
||||
# under two minutes.
|
||||
# tag to the existing manifest without re-uploading layers, and each
|
||||
# call is wrapped in 5-attempt exponential backoff so a transient
|
||||
# 429 / 5xx doesn't strand latest-* half-mirrored.
|
||||
#
|
||||
# Two registries: `ghcr.io/screenly/anthias-*` is the new primary
|
||||
# (rate-limit-friendly, free unlimited storage for public packages,
|
||||
# auth via the workflow-issued GITHUB_TOKEN with `packages: write`).
|
||||
# `screenly/anthias-*` on Docker Hub stays in the loop as a parallel
|
||||
# mirror during the migration window so devices that haven't yet
|
||||
# picked up the compose-template flip keep getting `latest-*`
|
||||
# advanced. GHCR is mirrored first so the canonical source is up to
|
||||
# date even if Docker Hub flakes on a later retag. The legacy
|
||||
# `screenly/srly-ose-*` namespace was dropped: every device that
|
||||
# has run `upgrade_containers.sh` since 2023-02 (b9998438) is on
|
||||
# `screenly/anthias-*` already, so the parallel `srly-ose-*` push
|
||||
# was buying no real back-compat in exchange for half the manifest
|
||||
# GETs (one of two reasons d568602's publish hit Docker Hub's 429).
|
||||
publish-latest:
|
||||
needs: buildx
|
||||
if: github.event_name == 'push'
|
||||
runs-on: ubuntu-24.04
|
||||
# See `buildx.permissions` above for rationale; same scoping reason.
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
@@ -152,13 +187,44 @@ jobs:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Mirror short-hash tags to latest-<board>
|
||||
run: |
|
||||
set -euo pipefail
|
||||
GIT_SHORT_HASH=$(git rev-parse --short=7 HEAD)
|
||||
BOARDS=(pi1 pi2 pi3 pi4 pi4-64 pi5 x86)
|
||||
SERVICES=(server celery redis viewer wifi-connect)
|
||||
NAMESPACES=(screenly/anthias screenly/srly-ose)
|
||||
# GHCR first so the canonical primary is current even if the
|
||||
# Docker Hub mirror later in the loop flakes.
|
||||
NAMESPACES=(ghcr.io/screenly/anthias screenly/anthias)
|
||||
|
||||
# Wrap a registry op in 5 attempts of exponential backoff
|
||||
# (2s, 4s, 8s, 16s) so a transient 429 / 5xx doesn't strand
|
||||
# `latest-*` half-mirrored. Both `imagetools inspect` and
|
||||
# `imagetools create` are idempotent: inspect is read-only,
|
||||
# and create overwrites the tag with the same manifest
|
||||
# digest on retry.
|
||||
retry() {
|
||||
local attempt
|
||||
for attempt in 1 2 3 4 5; do
|
||||
if "$@"; then
|
||||
return 0
|
||||
fi
|
||||
if [ "${attempt}" -lt 5 ]; then
|
||||
local delay=$((2 ** attempt))
|
||||
echo "Attempt ${attempt} failed; retrying in ${delay}s..." >&2
|
||||
sleep "${delay}"
|
||||
fi
|
||||
done
|
||||
echo "Giving up after 5 attempts: $*" >&2
|
||||
return 1
|
||||
}
|
||||
|
||||
echo "::group::Preflight: verify every <short-hash>-<board> source tag exists"
|
||||
for namespace in "${NAMESPACES[@]}"; do
|
||||
@@ -166,7 +232,7 @@ jobs:
|
||||
for board in "${BOARDS[@]}"; do
|
||||
src="${namespace}-${service}:${GIT_SHORT_HASH}-${board}"
|
||||
echo "Verifying ${src}"
|
||||
docker buildx imagetools inspect --raw "${src}" >/dev/null
|
||||
retry docker buildx imagetools inspect --raw "${src}" >/dev/null
|
||||
done
|
||||
done
|
||||
done
|
||||
@@ -179,7 +245,7 @@ jobs:
|
||||
src="${namespace}-${service}:${GIT_SHORT_HASH}-${board}"
|
||||
dst="${namespace}-${service}:latest-${board}"
|
||||
echo "Mirroring ${src} -> ${dst}"
|
||||
docker buildx imagetools create -t "${dst}" "${src}"
|
||||
retry docker buildx imagetools create -t "${dst}" "${src}"
|
||||
done
|
||||
done
|
||||
done
|
||||
|
||||
@@ -12,12 +12,24 @@ import secrets
|
||||
from os import getenv
|
||||
from pathlib import Path
|
||||
|
||||
import django_stubs_ext
|
||||
import pytz
|
||||
|
||||
from settings import settings as device_settings
|
||||
|
||||
django_stubs_ext.monkeypatch()
|
||||
# django_stubs_ext.monkeypatch() makes Django generic classes
|
||||
# subscriptable at runtime, and the server side of this repo relies on
|
||||
# that — anthias_app/admin.py defines `class AssetAdmin(admin.ModelAdmin
|
||||
# [Asset])` at import time, which raises TypeError without the patch.
|
||||
# Keep the import optional so the viewer image (and any future service
|
||||
# that doesn't ship django-stubs-ext) can still load this settings
|
||||
# module; do not remove the patch as a no-op.
|
||||
try:
|
||||
import django_stubs_ext
|
||||
|
||||
django_stubs_ext.monkeypatch()
|
||||
except ModuleNotFoundError as exc:
|
||||
if exc.name != 'django_stubs_ext':
|
||||
raise
|
||||
|
||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||
@@ -66,21 +78,34 @@ ALLOWED_HOSTS = [
|
||||
|
||||
# Application definition
|
||||
|
||||
# Apps every Django consumer needs: ORM access to the Asset model,
|
||||
# plus the contenttypes + auth tables those models implicitly depend
|
||||
# on. Loaded by every service that calls django.setup() — server,
|
||||
# celery, viewer, test.
|
||||
INSTALLED_APPS = [
|
||||
'channels',
|
||||
'anthias_app.apps.AnthiasAppConfig',
|
||||
'drf_spectacular',
|
||||
'rest_framework',
|
||||
'api.apps.ApiConfig',
|
||||
'django.contrib.admin',
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'dbbackup',
|
||||
'django.contrib.auth',
|
||||
]
|
||||
|
||||
# Apps only the HTTP-serving services need (REST API, OpenAPI schema,
|
||||
# Channels for WebSockets, the admin UI, sessions/messages, static
|
||||
# files, DB backups). The viewer never serves HTTP, so it skips these
|
||||
# at django.setup() time and the viewer image doesn't have to ship
|
||||
# the packages they live in. Server/celery/test images are unaffected.
|
||||
if getenv('ANTHIAS_SERVICE') != 'viewer':
|
||||
INSTALLED_APPS += [
|
||||
'channels',
|
||||
'drf_spectacular',
|
||||
'rest_framework',
|
||||
'api.apps.ApiConfig',
|
||||
'django.contrib.admin',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'dbbackup',
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
'whitenoise.middleware.WhiteNoiseMiddleware',
|
||||
|
||||
@@ -8,20 +8,17 @@ import sh
|
||||
from celery import Celery
|
||||
from tenacity import Retrying, stop_after_attempt, wait_fixed
|
||||
|
||||
try:
|
||||
django.setup()
|
||||
django.setup()
|
||||
|
||||
# Place imports that uses Django in this block.
|
||||
# Place imports that uses Django in this block.
|
||||
|
||||
from lib import diagnostics
|
||||
from lib.utils import (
|
||||
connect_to_redis,
|
||||
is_balena_app,
|
||||
reboot_via_balena_supervisor,
|
||||
shutdown_via_balena_supervisor,
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
from lib import diagnostics # noqa: E402
|
||||
from lib.utils import ( # noqa: E402
|
||||
connect_to_redis,
|
||||
is_balena_app,
|
||||
reboot_via_balena_supervisor,
|
||||
shutdown_via_balena_supervisor,
|
||||
)
|
||||
|
||||
|
||||
__author__ = 'Screenly, Inc'
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
version: "2"
|
||||
services:
|
||||
anthias-wifi-connect:
|
||||
image: screenly/anthias-wifi-connect:${GIT_SHORT_HASH}-${BOARD}
|
||||
image: ghcr.io/screenly/anthias-wifi-connect:${GIT_SHORT_HASH}-${BOARD}
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./docker/Dockerfile.wifi-connect
|
||||
@@ -21,7 +21,7 @@ services:
|
||||
io.balena.features.firmware: "1"
|
||||
|
||||
anthias-server:
|
||||
image: screenly/anthias-server:${GIT_SHORT_HASH}-${BOARD}
|
||||
image: ghcr.io/screenly/anthias-server:${GIT_SHORT_HASH}-${BOARD}
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./docker/Dockerfile.server
|
||||
@@ -43,7 +43,7 @@ services:
|
||||
io.balena.features.supervisor-api: '1'
|
||||
|
||||
anthias-viewer:
|
||||
image: screenly/anthias-viewer:${GIT_SHORT_HASH}-${BOARD}
|
||||
image: ghcr.io/screenly/anthias-viewer:${GIT_SHORT_HASH}-${BOARD}
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./docker/Dockerfile.viewer
|
||||
@@ -65,7 +65,7 @@ services:
|
||||
io.balena.features.supervisor-api: '1'
|
||||
|
||||
anthias-celery:
|
||||
image: screenly/anthias-celery:${GIT_SHORT_HASH}-${BOARD}
|
||||
image: ghcr.io/screenly/anthias-celery:${GIT_SHORT_HASH}-${BOARD}
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./docker/Dockerfile.celery
|
||||
@@ -85,7 +85,7 @@ services:
|
||||
io.balena.features.supervisor-api: '1'
|
||||
|
||||
redis:
|
||||
image: screenly/anthias-redis:${GIT_SHORT_HASH}-${BOARD}
|
||||
image: ghcr.io/screenly/anthias-redis:${GIT_SHORT_HASH}-${BOARD}
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./docker/Dockerfile.redis
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
version: "2"
|
||||
services:
|
||||
anthias-wifi-connect:
|
||||
image: screenly/anthias-wifi-connect:${GIT_SHORT_HASH}-${BOARD}
|
||||
image: ghcr.io/screenly/anthias-wifi-connect:${GIT_SHORT_HASH}-${BOARD}
|
||||
depends_on:
|
||||
- anthias-viewer
|
||||
environment:
|
||||
@@ -18,7 +18,7 @@ services:
|
||||
io.balena.features.firmware: "1"
|
||||
|
||||
anthias-server:
|
||||
image: screenly/anthias-server:${GIT_SHORT_HASH}-${BOARD}
|
||||
image: ghcr.io/screenly/anthias-server:${GIT_SHORT_HASH}-${BOARD}
|
||||
ports:
|
||||
- 80:8080
|
||||
environment:
|
||||
@@ -37,7 +37,7 @@ services:
|
||||
io.balena.features.supervisor-api: '1'
|
||||
|
||||
anthias-viewer:
|
||||
image: screenly/anthias-viewer:${GIT_SHORT_HASH}-${BOARD}
|
||||
image: ghcr.io/screenly/anthias-viewer:${GIT_SHORT_HASH}-${BOARD}
|
||||
depends_on:
|
||||
- anthias-server
|
||||
environment:
|
||||
@@ -56,7 +56,7 @@ services:
|
||||
io.balena.features.supervisor-api: '1'
|
||||
|
||||
anthias-celery:
|
||||
image: screenly/anthias-celery:${GIT_SHORT_HASH}-${BOARD}
|
||||
image: ghcr.io/screenly/anthias-celery:${GIT_SHORT_HASH}-${BOARD}
|
||||
depends_on:
|
||||
- anthias-server
|
||||
- redis
|
||||
@@ -73,7 +73,7 @@ services:
|
||||
io.balena.features.supervisor-api: '1'
|
||||
|
||||
redis:
|
||||
image: screenly/anthias-redis:${GIT_SHORT_HASH}-${BOARD}
|
||||
image: ghcr.io/screenly/anthias-redis:${GIT_SHORT_HASH}-${BOARD}
|
||||
ports:
|
||||
- 127.0.0.1:6379:6379
|
||||
restart: always
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
services:
|
||||
anthias-wifi-connect:
|
||||
image: screenly/anthias-wifi-connect:${DOCKER_TAG}-${DEVICE_TYPE}
|
||||
image: ghcr.io/screenly/anthias-wifi-connect:${DOCKER_TAG}-${DEVICE_TYPE}
|
||||
build:
|
||||
context: .
|
||||
dockerfile: docker/Dockerfile.wifi-connect
|
||||
@@ -21,7 +21,7 @@ services:
|
||||
target: /run/dbus/system_bus_socket
|
||||
|
||||
anthias-server:
|
||||
image: screenly/anthias-server:${DOCKER_TAG}-${DEVICE_TYPE}
|
||||
image: ghcr.io/screenly/anthias-server:${DOCKER_TAG}-${DEVICE_TYPE}
|
||||
build:
|
||||
context: .
|
||||
dockerfile: docker/Dockerfile.server
|
||||
@@ -51,7 +51,7 @@ services:
|
||||
io.balena.features.supervisor-api: '1'
|
||||
|
||||
anthias-viewer:
|
||||
image: screenly/anthias-viewer:${DOCKER_TAG}-${DEVICE_TYPE}
|
||||
image: ghcr.io/screenly/anthias-viewer:${DOCKER_TAG}-${DEVICE_TYPE}
|
||||
build:
|
||||
context: .
|
||||
dockerfile: docker/Dockerfile.viewer
|
||||
@@ -79,7 +79,7 @@ services:
|
||||
io.balena.features.supervisor-api: '1'
|
||||
|
||||
anthias-celery:
|
||||
image: screenly/anthias-celery:${DOCKER_TAG}-${DEVICE_TYPE}
|
||||
image: ghcr.io/screenly/anthias-celery:${DOCKER_TAG}-${DEVICE_TYPE}
|
||||
build:
|
||||
context: .
|
||||
dockerfile: docker/Dockerfile.celery
|
||||
@@ -103,7 +103,7 @@ services:
|
||||
io.balena.features.supervisor-api: '1'
|
||||
|
||||
redis:
|
||||
image: screenly/anthias-redis:${DOCKER_TAG}-${DEVICE_TYPE}
|
||||
image: ghcr.io/screenly/anthias-redis:${DOCKER_TAG}-${DEVICE_TYPE}
|
||||
build:
|
||||
context: .
|
||||
dockerfile: docker/Dockerfile.redis
|
||||
|
||||
@@ -19,3 +19,4 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
|
||||
# https://github.com/balena-io-library/base-images/issues/562
|
||||
RUN c_rehash
|
||||
|
||||
{% include 'labels.j2' %}
|
||||
|
||||
@@ -19,5 +19,7 @@ ENV GIT_BRANCH={{ git_branch }}
|
||||
RUN sed -i 's/^bind.*/bind 0.0.0.0/g' /etc/redis/redis.conf
|
||||
RUN sed -i 's/^protected-mode.*/protected-mode no/g' /etc/redis/redis.conf
|
||||
|
||||
{% include 'labels.j2' %}
|
||||
|
||||
CMD ["redis-server", "--protected-mode", "no"]
|
||||
|
||||
|
||||
@@ -61,6 +61,7 @@ ENV GIT_SHORT_HASH={{ git_short_hash }}
|
||||
ENV GIT_BRANCH={{ git_branch }}
|
||||
ENV DEVICE_TYPE={{ board }}
|
||||
ENV DJANGO_SETTINGS_MODULE="anthias_django.settings"
|
||||
ENV ANTHIAS_SERVICE="viewer"
|
||||
|
||||
RUN useradd -g video viewer
|
||||
|
||||
@@ -70,4 +71,6 @@ WORKDIR /usr/src/app
|
||||
RUN mkdir -p /usr/src/app
|
||||
COPY . /usr/src/app/
|
||||
|
||||
{% include 'labels.j2' %}
|
||||
|
||||
CMD ["bash", "./bin/start_viewer.sh"]
|
||||
|
||||
19
docker/labels.j2
Normal file
19
docker/labels.j2
Normal file
@@ -0,0 +1,19 @@
|
||||
{# OCI image labels (https://specs.opencontainers.org/image-spec/annotations/).
|
||||
`image.source` is the load-bearing one for GitHub Container Registry:
|
||||
GHCR uses it to link the package to its source repo, which makes the
|
||||
package inherit the repo's visibility and grants repo collaborators
|
||||
push/delete access. Without it, packages stay private even when the
|
||||
repo is public, and the package page on GitHub has no link back. #}
|
||||
{% set service_descriptions = {
|
||||
'server': 'Anthias web server (uvicorn + Django + Channels)',
|
||||
'celery': 'Anthias background task worker (asset downloads, cleanup, display power)',
|
||||
'redis': 'Redis broker for Anthias Celery and Channels',
|
||||
'viewer': 'Anthias display/viewer service',
|
||||
'wifi-connect': 'Anthias WiFi captive-portal helper',
|
||||
'test': 'Anthias test runner',
|
||||
} %}
|
||||
LABEL org.opencontainers.image.source="https://github.com/Screenly/Anthias"
|
||||
LABEL org.opencontainers.image.url="https://anthias.screenly.io"
|
||||
LABEL org.opencontainers.image.licenses="GPL-2.0"
|
||||
LABEL org.opencontainers.image.title="anthias-{{ service }}"
|
||||
LABEL org.opencontainers.image.description="{{ service_descriptions.get(service, 'Anthias ' + service) }}"
|
||||
@@ -78,8 +78,6 @@ viewer = [
|
||||
"cryptography==46.0.7",
|
||||
"Cython==3.2.4",
|
||||
"Django==4.2.30",
|
||||
"django-dbbackup==4.2.1",
|
||||
"drf-spectacular==0.29.0",
|
||||
"future==1.0.0",
|
||||
"idna==3.11",
|
||||
"Jinja2==3.1.6",
|
||||
|
||||
@@ -106,6 +106,7 @@ def build_image(
|
||||
'git_branch': git_branch,
|
||||
'git_hash': git_hash,
|
||||
'git_short_hash': git_short_hash,
|
||||
'service': service,
|
||||
'target_platform': target_platform,
|
||||
**context,
|
||||
},
|
||||
@@ -236,8 +237,22 @@ def main(
|
||||
|
||||
# Build Docker images
|
||||
for service_name in services_to_build:
|
||||
# Define tag components
|
||||
namespaces = ['screenly/anthias', 'screenly/srly-ose']
|
||||
# Define tag components.
|
||||
#
|
||||
# GHCR is listed first because it is the primary, canonical source
|
||||
# for Anthias images going forward — `bin/upgrade_containers.sh`
|
||||
# regenerates compose from `docker-compose.yml.tmpl`, so flipping
|
||||
# the template (separate change) flips every device on next
|
||||
# upgrade. Docker Hub stays in the list as a parallel push during
|
||||
# the migration window so devices that haven't yet picked up the
|
||||
# template flip keep getting `latest-*` advanced.
|
||||
#
|
||||
# The legacy `screenly/srly-ose-*` namespace was dropped: every
|
||||
# device that has run `upgrade_containers.sh` since 2023-02
|
||||
# (b9998438) is on `screenly/anthias-*`, and stale `srly-ose-*`
|
||||
# `latest-*` mirroring (one of two reasons d568602 hit Docker
|
||||
# Hub's 429) gives no real back-compat in exchange.
|
||||
namespaces = ['ghcr.io/screenly/anthias', 'screenly/anthias']
|
||||
version_suffix = (
|
||||
f'{board}-64'
|
||||
if board == 'pi4' and platform == 'linux/arm64/v8'
|
||||
|
||||
4
uv.lock
generated
4
uv.lock
generated
@@ -267,8 +267,6 @@ viewer = [
|
||||
{ name = "cryptography" },
|
||||
{ name = "cython" },
|
||||
{ name = "django" },
|
||||
{ name = "django-dbbackup" },
|
||||
{ name = "drf-spectacular" },
|
||||
{ name = "future" },
|
||||
{ name = "idna" },
|
||||
{ name = "jinja2" },
|
||||
@@ -468,8 +466,6 @@ viewer = [
|
||||
{ name = "cryptography", specifier = "==46.0.7" },
|
||||
{ name = "cython", specifier = "==3.2.4" },
|
||||
{ name = "django", specifier = "==4.2.30" },
|
||||
{ name = "django-dbbackup", specifier = "==4.2.1" },
|
||||
{ name = "drf-spectacular", specifier = "==0.29.0" },
|
||||
{ name = "future", specifier = "==1.0.0" },
|
||||
{ name = "idna", specifier = "==3.11" },
|
||||
{ name = "jinja2", specifier = "==3.1.6" },
|
||||
|
||||
@@ -32,23 +32,20 @@ from viewer.utils import (
|
||||
watchdog,
|
||||
)
|
||||
|
||||
try:
|
||||
django.setup()
|
||||
django.setup()
|
||||
|
||||
# Place imports that uses Django in this block.
|
||||
# Place imports that uses Django in this block.
|
||||
|
||||
from lib.utils import (
|
||||
connect_to_redis,
|
||||
get_balena_device_info,
|
||||
get_node_ip,
|
||||
is_balena_app,
|
||||
string_to_bool,
|
||||
url_fails,
|
||||
)
|
||||
from viewer.messaging import ViewerSubscriber
|
||||
from viewer.scheduling import Scheduler
|
||||
except Exception:
|
||||
pass
|
||||
from lib.utils import ( # noqa: E402
|
||||
connect_to_redis,
|
||||
get_balena_device_info,
|
||||
get_node_ip,
|
||||
is_balena_app,
|
||||
string_to_bool,
|
||||
url_fails,
|
||||
)
|
||||
from viewer.messaging import ViewerSubscriber # noqa: E402
|
||||
from viewer.scheduling import Scheduler # noqa: E402
|
||||
|
||||
|
||||
__author__ = 'Screenly, Inc'
|
||||
|
||||
Reference in New Issue
Block a user