diff --git a/.coverage b/.coverage index 7e67345e..71b99e5b 100644 Binary files a/.coverage and b/.coverage differ diff --git a/.github/workflows/jest-tests.yml b/.github/workflows/jest-tests.yml index b33a9c2a..e3d01975 100644 --- a/.github/workflows/jest-tests.yml +++ b/.github/workflows/jest-tests.yml @@ -12,16 +12,11 @@ jobs: - uses: actions/setup-node@v2 with: node-version: '12' - - name: Install Code Climate test-reporter - run: | - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter - chmod +x ./cc-test-reporter - name: Install modules run: npm ci - name: Run tests env: CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }} - run: | - ./cc-test-reporter before-build - npm run test - ./cc-test-reporter after-build --exit-code $? \ No newline at end of file + run: npm run test + - name: Submit to Codecov + uses: codecov/codecov-action@v1 \ No newline at end of file diff --git a/.github/workflows/python-tests.yml b/.github/workflows/python-tests.yml index ccef1bc6..d00dd425 100644 --- a/.github/workflows/python-tests.yml +++ b/.github/workflows/python-tests.yml @@ -5,21 +5,50 @@ on: - pull_request jobs: - build: - runs-on: ubuntu-latest + main: strategy: + fail-fast: false matrix: - python-version: [3.7, 3.8] + include: + - name: "Test: Python 3.7" + python: "3.7" + tox: py37 + coverage: true + - name: "Test: Python 3.8" + python: "3.8" + tox: py38 + - name: "Test: Python 3.9" + python: "3.9" + tox: py39 + - name: "Lint: check-manifest" + python: "3.9" + tox: check-manifest + - name: "Lint: flake8" + python: "3.9" + tox: flake8 + + name: ${{ matrix.name }} + runs-on: ubuntu-20.04 + container: ghcr.io/mopidy/ci:latest steps: - - uses: actions/checkout@v1 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install tox tox-gh-actions - - name: Test with tox - run: tox + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python }} + - name: Fix home dir permissions to enable pip caching + run: chown -R root /github/home + - name: Cache pip + uses: actions/cache@v2 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-${{ matrix.python }}-${{ matrix.tox }}-pip-${{ hashFiles('setup.cfg') }}-${{ hashFiles('tox.ini') }} + restore-keys: | + ${{ runner.os }}-${{ matrix.python }}-${{ matrix.tox }}-pip- + - run: python -m pip install pygobject tox + - run: python -m tox -e ${{ matrix.tox }} + if: ${{ ! matrix.coverage }} + - run: python -m tox -e ${{ matrix.tox }} -- --cov-report=xml + if: ${{ matrix.coverage }} + - uses: codecov/codecov-action@v1 + if: ${{ matrix.coverage }} \ No newline at end of file diff --git a/.github/workflows/build-docker.yml b/.github/workflows/release.yml similarity index 60% rename from .github/workflows/build-docker.yml rename to .github/workflows/release.yml index 7d5efa4b..46dc8b60 100644 --- a/.github/workflows/build-docker.yml +++ b/.github/workflows/release.yml @@ -1,4 +1,4 @@ -name: Build Docker +name: Release on: push: @@ -6,12 +6,34 @@ on: jobs: build-and-push-docker-image: - name: Build image and push to DockerHub + name: Build and publish to PyPi and DockerHub runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v2 + + - name: Setup Node + uses: actions/setup-node@v2 + with: + node-version: '12' + + - name: Install JS dependencies + run: npm install + + - name: Build JS + run: npm run build:prod + + - name: Setup Python + uses: actions/setup-python@v2 + with: + python-version: '3.7' + + - name: "Install Python dependencies" + run: python3 -m pip install build + + - name: "Build Python package" + run: python3 -m build - name: Set up Docker Buildx id: buildx @@ -39,5 +61,11 @@ jobs: # build on feature branches, push only on master branch push: ${{ github.ref == 'refs/heads/master' }} + - name: Publish to Pypi + uses: pypa/gh-action-pypi-publish@v1.4.1 + with: + user: __token__ + password: ${{ secrets.PYPI_TOKEN }} + - name: Image digest run: echo ${{ steps.docker_build.outputs.digest }} diff --git a/IRIS_VERSION b/IRIS_VERSION index 71c01095..09a5d91f 100755 --- a/IRIS_VERSION +++ b/IRIS_VERSION @@ -1 +1 @@ -3.60.0 +3.60.1 diff --git a/MANIFEST.in b/MANIFEST.in index d434987a..7b574744 100755 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,13 +1,16 @@ recursive-include mopidy_iris/static * recursive-include mopidy_iris *.py recursive-include docs * -recursive-include __tests__ *.py -recursive-include __tests__ *.js -recursive-include __mocks__ *.js +recursive-include __tests__ * +recursive-include __mocks__ * include mopidy_iris/ext.conf include mopidy_iris/system.sh include IRIS_VERSION include Dockerfile include pyproject.toml include screenshot.jpg -include tox.ini \ No newline at end of file +include tox.ini +recursive-exclude src * +exclude .jshintrc +exclude .babelrc +exclude jest.config.js \ No newline at end of file diff --git a/mopidy_iris/core.py b/mopidy_iris/core.py index ba045c01..9dfbe111 100755 --- a/mopidy_iris/core.py +++ b/mopidy_iris/core.py @@ -1157,9 +1157,10 @@ class IrisCore(pykka.ThreadingActor): # Uses snapcast server and stream details as defined in configuration ## async def update_snapcast_meta(self, *args, **kwargs): + callback = kwargs.get("callback", False) track = self.core.playback.get_current_track().get() meta = {} - + if track: # Convert the Track to JSON, but to make it a response-ready JSON we need to load it. # Required because ModelJSONEncoder produces single-quote JSON, and we need standard @@ -1168,10 +1169,7 @@ class IrisCore(pykka.ThreadingActor): images = self.core.library.get_images([track["uri"]]).get() if images: meta["images"] = json.loads( - json.dumps( - images[track["uri"]], - cls=ModelJSONEncoder - ) + json.dumps(images[track["uri"]], cls=ModelJSONEncoder) ) meta["name"] = track["name"] meta["uri"] = track["uri"] @@ -1191,8 +1189,8 @@ class IrisCore(pykka.ThreadingActor): "method": "Stream.SetMeta", "params": { "id": self.config["iris"]["snapcast_stream"], - "meta": meta - } + "meta": meta, + }, } try: @@ -1202,10 +1200,19 @@ class IrisCore(pykka.ThreadingActor): ) except (urllib.error.HTTPError, urllib.error.URLError) as e: error = json.loads(e.read()) - logger.error('Could not update Snapcast meta', error) + logger.error("Could not update Snapcast meta") + response = { + "message": "Could not update Snapcast meta", + error: error, + } except Exception as e: logger.error(e) - pass # Non-blocking error; TODO more elegantly catch exception without killing Mopidy + response = {"message": "Could not update Snapcast meta"} + + if callback: + callback(response) + else: + return response ## # Simple test method to debug access to system tasks diff --git a/setup.cfg b/setup.cfg index a884734a..be4ff1bd 100755 --- a/setup.cfg +++ b/setup.cfg @@ -63,7 +63,7 @@ mopidy.ext = [flake8] application-import-names = mopidy_iris, tests -max-line-length = 80 +max-line-length = 100 select = # Regular flake8 rules C, E, F, W diff --git a/src/js/components/Fields/OutputControl.js b/src/js/components/Fields/OutputControl.js index 454774de..d6484561 100755 --- a/src/js/components/Fields/OutputControl.js +++ b/src/js/components/Fields/OutputControl.js @@ -91,9 +91,13 @@ const Group = ({ }) => { const allClients = useSelector((state) => state.snapcast.clients || {}); const allStreams = indexToArray(useSelector((state) => state.snapcast.streams || {})); - const clients = clients_ids.length > 0 ? clients_ids.map((c) => allClients[c]) : []; + const clients = clients_ids.length > 0 + ? clients_ids.map((c) => allClients[c]).filter((c) => c.connected) + : []; const dispatch = useDispatch(); + if (!clients || !clients.length) return null; + return (