Merge pull request #18453 from gustavotrott/merge-27-into-develop-4ago2023
Merge 2.7 into Develop
This commit is contained in:
commit
dc75850f1a
408
.github/workflows/automated-tests.yml
vendored
408
.github/workflows/automated-tests.yml
vendored
@ -16,26 +16,99 @@ on:
|
|||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
jobs:
|
jobs:
|
||||||
build-install-and-test:
|
build-bbb-apps-akka:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
fetch-depth: 0 # Fetch all history
|
||||||
|
- run: echo "CACHE_AKKA_APPS_KEY=$(git log -1 --format=%H -- akka-bbb-apps)" >> $GITHUB_ENV
|
||||||
|
- run: echo "CACHE_COMMON_MSG_KEY=$(git log -1 --format=%H -- bbb-common-message)" >> $GITHUB_ENV
|
||||||
|
- run: echo "CACHE_BBB_RELEASE_KEY=$(git log -1 --format=%H -- bigbluebutton-config/bigbluebutton-release)" >> $GITHUB_ENV
|
||||||
|
- run: echo "FORCE_GIT_REV=0" >> $GITHUB_ENV #used by setup.sh
|
||||||
|
- run: echo "FORCE_COMMIT_DATE=0" >> $GITHUB_ENV #used by setup.sh
|
||||||
|
- name: Handle cache
|
||||||
|
id: cache-action
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: artifacts.tar
|
||||||
|
key: ${{ runner.os }}-bbb-apps-akka-${{ env.CACHE_AKKA_APPS_KEY }}-${{ env.CACHE_COMMON_MSG_KEY }}-${{ env.CACHE_BBB_RELEASE_KEY }}
|
||||||
|
- if: ${{ steps.cache-action.outputs.cache-hit != 'true' }}
|
||||||
|
name: Generate artifacts
|
||||||
|
run: |
|
||||||
|
./build/get_external_dependencies.sh
|
||||||
|
./build/setup.sh bbb-apps-akka
|
||||||
|
tar cvf artifacts.tar artifacts/
|
||||||
|
- name: Archive packages
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: artifacts_bbb-apps-akka.tar
|
||||||
|
path: |
|
||||||
|
artifacts.tar
|
||||||
|
build-bbb-config:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- run: echo "FORCE_GIT_REV=0" >> $GITHUB_ENV #used by setup.sh
|
||||||
|
- run: echo "FORCE_COMMIT_DATE=0" >> $GITHUB_ENV #used by setup.sh
|
||||||
|
- run: |
|
||||||
|
./build/get_external_dependencies.sh
|
||||||
|
./build/setup.sh bbb-config
|
||||||
|
tar cvf artifacts.tar artifacts/
|
||||||
|
- name: Archive packages
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: artifacts_bbb-config.tar
|
||||||
|
path: artifacts.tar
|
||||||
|
build-bbb-export-annotations:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- run: echo "FORCE_GIT_REV=0" >> $GITHUB_ENV #used by setup.sh
|
||||||
|
- run: echo "FORCE_COMMIT_DATE=0" >> $GITHUB_ENV #used by setup.sh
|
||||||
|
- run: |
|
||||||
|
./build/get_external_dependencies.sh
|
||||||
|
./build/setup.sh bbb-export-annotations
|
||||||
|
tar cvf artifacts.tar artifacts/
|
||||||
|
- name: Archive packages
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: artifacts_bbb-export-annotations.tar
|
||||||
|
path: artifacts.tar
|
||||||
|
build-bbb-learning-dashboard:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
fetch-depth: 0 # Fetch all history
|
||||||
|
- run: echo "CACHE_LEARNING_DASHBOARD_KEY=$(git log -1 --format=%H -- bbb-learning-dashboard)" >> $GITHUB_ENV
|
||||||
|
- run: echo "CACHE_BBB_RELEASE_KEY=$(git log -1 --format=%H -- bigbluebutton-config/bigbluebutton-release)" >> $GITHUB_ENV
|
||||||
|
- run: echo "FORCE_GIT_REV=0" >> $GITHUB_ENV #used by setup.sh
|
||||||
|
- run: echo "FORCE_COMMIT_DATE=0" >> $GITHUB_ENV #used by setup.sh
|
||||||
|
- name: Handle cache
|
||||||
|
id: cache-action
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: artifacts.tar
|
||||||
|
key: ${{ runner.os }}-bbb-learning-dashboard-${{ env.CACHE_LEARNING_DASHBOARD_KEY }}-${{ env.CACHE_BBB_RELEASE_KEY }}
|
||||||
|
- if: ${{ steps.cache-action.outputs.cache-hit != 'true' }}
|
||||||
|
name: Generate artifacts
|
||||||
|
run: |
|
||||||
|
./build/get_external_dependencies.sh
|
||||||
|
./build/setup.sh bbb-learning-dashboard
|
||||||
|
tar cvf artifacts.tar artifacts/
|
||||||
|
- name: Archive packages
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: artifacts_bbb-learning-dashboard.tar
|
||||||
|
path: artifacts.tar
|
||||||
|
build-bbb-playback-record:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- run: ./build/get_external_dependencies.sh
|
- run: ./build/get_external_dependencies.sh
|
||||||
- run: ./build/setup.sh bbb-apps-akka
|
- run: echo "FORCE_GIT_REV=0" >> $GITHUB_ENV #used by setup.sh
|
||||||
- run: ./build/setup.sh bbb-config
|
- run: echo "FORCE_COMMIT_DATE=0" >> $GITHUB_ENV #used by setup.sh
|
||||||
- run: ./build/setup.sh bbb-etherpad
|
|
||||||
- run: ./build/setup.sh bbb-export-annotations
|
|
||||||
- run: ./build/setup.sh bbb-freeswitch-core
|
|
||||||
- run: ./build/setup.sh bbb-freeswitch-sounds
|
|
||||||
- run: ./build/setup.sh bbb-fsesl-akka
|
|
||||||
- run: ./build/setup.sh bbb-graphql-middleware
|
|
||||||
- run: ./build/setup.sh bbb-graphql-server
|
|
||||||
- run: ./build/setup.sh bbb-html5-nodejs
|
|
||||||
- run: ./build/setup.sh bbb-html5
|
|
||||||
- run: ./build/setup.sh bbb-learning-dashboard
|
|
||||||
- run: ./build/setup.sh bbb-libreoffice-docker
|
|
||||||
- run: ./build/setup.sh bbb-mkclean
|
|
||||||
- run: ./build/setup.sh bbb-pads
|
|
||||||
- run: ./build/setup.sh bbb-playback
|
- run: ./build/setup.sh bbb-playback
|
||||||
- run: ./build/setup.sh bbb-playback-notes
|
- run: ./build/setup.sh bbb-playback-notes
|
||||||
- run: ./build/setup.sh bbb-playback-podcast
|
- run: ./build/setup.sh bbb-playback-podcast
|
||||||
@ -43,7 +116,191 @@ jobs:
|
|||||||
- run: ./build/setup.sh bbb-playback-screenshare
|
- run: ./build/setup.sh bbb-playback-screenshare
|
||||||
- run: ./build/setup.sh bbb-playback-video
|
- run: ./build/setup.sh bbb-playback-video
|
||||||
- run: ./build/setup.sh bbb-record-core
|
- run: ./build/setup.sh bbb-record-core
|
||||||
- run: ./build/setup.sh bbb-web
|
- run: tar cvf artifacts.tar artifacts/
|
||||||
|
- name: Archive packages
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: artifacts_bbb-playback-record.tar
|
||||||
|
path: |
|
||||||
|
artifacts.tar
|
||||||
|
build-bbb-graphql-server:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- run: ./build/get_external_dependencies.sh
|
||||||
|
- run: echo "FORCE_GIT_REV=0" >> $GITHUB_ENV #used by setup.sh
|
||||||
|
- run: echo "FORCE_COMMIT_DATE=0" >> $GITHUB_ENV #used by setup.sh
|
||||||
|
- run: ./build/setup.sh bbb-graphql-middleware
|
||||||
|
- run: ./build/setup.sh bbb-graphql-server
|
||||||
|
- run: tar cvf artifacts.tar artifacts/
|
||||||
|
- name: Archive packages
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: artifacts_bbb-graphql-server.tar
|
||||||
|
path: |
|
||||||
|
artifacts.tar
|
||||||
|
build-bbb-etherpad:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
fetch-depth: 0 # Fetch all history
|
||||||
|
- run: echo "CACHE_ETHERPAD_VERSION_KEY=$(git log -1 --format=%H -- bbb-etherpad.placeholder.sh)" >> $GITHUB_ENV
|
||||||
|
- run: echo "CACHE_ETHERPAD_BUILD_KEY=$(git log -1 --format=%H -- build/packages-template/bbb-etherpad)" >> $GITHUB_ENV
|
||||||
|
- run: echo "CACHE_URL1_KEY=$(curl -s https://api.github.com/repos/mconf/ep_pad_ttl/commits | md5sum | awk '{ print $1 }')" >> $GITHUB_ENV
|
||||||
|
- run: echo "CACHE_URL2_KEY=$(curl -s https://api.github.com/repos/alangecker/bbb-etherpad-plugin/commits | md5sum | awk '{ print $1 }')" >> $GITHUB_ENV
|
||||||
|
- run: echo "CACHE_URL3_KEY=$(curl -s https://api.github.com/repos/mconf/ep_redis_publisher/commits | md5sum | awk '{ print $1 }')" >> $GITHUB_ENV
|
||||||
|
- run: echo "CACHE_URL4_KEY=$(curl -s https://api.github.com/repos/alangecker/bbb-etherpad-skin/commits | md5sum | awk '{ print $1 }')" >> $GITHUB_ENV
|
||||||
|
- run: echo "CACHE_BBB_RELEASE_KEY=$(git log -1 --format=%H -- bigbluebutton-config/bigbluebutton-release)" >> $GITHUB_ENV
|
||||||
|
- run: echo "FORCE_GIT_REV=0" >> $GITHUB_ENV #used by setup.sh
|
||||||
|
- run: echo "FORCE_COMMIT_DATE=0" >> $GITHUB_ENV #used by setup.sh
|
||||||
|
- name: Handle cache
|
||||||
|
id: cache-action
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: artifacts.tar
|
||||||
|
key: ${{ runner.os }}-bbb-etherpad-${{ env.CACHE_ETHERPAD_VERSION_KEY }}-${{ env.CACHE_ETHERPAD_BUILD_KEY }}-${{ env.CACHE_URL1_KEY }}-${{ env.CACHE_URL2_KEY }}-${{ env.CACHE_URL3_KEY }}-${{ env.CACHE_URL4_KEY }}-${{ env.CACHE_BBB_RELEASE_KEY }}
|
||||||
|
- if: ${{ steps.cache-action.outputs.cache-hit != 'true' }}
|
||||||
|
name: Generate artifacts
|
||||||
|
run: |
|
||||||
|
./build/get_external_dependencies.sh
|
||||||
|
./build/setup.sh bbb-etherpad
|
||||||
|
tar cvf artifacts.tar artifacts/
|
||||||
|
- name: Archive packages
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: artifacts_bbb-etherpad.tar
|
||||||
|
path: |
|
||||||
|
artifacts.tar
|
||||||
|
build-bbb-bbb-web:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
fetch-depth: 0 # Fetch all history
|
||||||
|
- run: echo "CACHE_BBB_WEB_KEY=$(git log -1 --format=%H -- bigbluebutton-web)" >> $GITHUB_ENV
|
||||||
|
- run: echo "CACHE_COMMON_MSG_KEY=$(git log -1 --format=%H -- bbb-common-message)" >> $GITHUB_ENV
|
||||||
|
- run: echo "CACHE_COMMON_WEB_KEY=$(git log -1 --format=%H -- bbb-common-web)" >> $GITHUB_ENV
|
||||||
|
- run: echo "CACHE_BBB_RELEASE_KEY=$(git log -1 --format=%H -- bigbluebutton-config/bigbluebutton-release)" >> $GITHUB_ENV
|
||||||
|
- run: echo "FORCE_GIT_REV=0" >> $GITHUB_ENV #used by setup.sh
|
||||||
|
- run: echo "FORCE_COMMIT_DATE=0" >> $GITHUB_ENV #used by setup.sh
|
||||||
|
- name: Handle cache
|
||||||
|
id: cache-action
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: artifacts.tar
|
||||||
|
key: ${{ runner.os }}-bbb-web-${{ env.CACHE_BBB_WEB_KEY }}-${{ env.CACHE_COMMON_MSG_KEY }}-${{ env.CACHE_COMMON_WEB_KEY }}-${{ env.CACHE_BBB_RELEASE_KEY }}
|
||||||
|
- if: ${{ steps.cache-action.outputs.cache-hit != 'true' }}
|
||||||
|
name: Generate artifacts
|
||||||
|
run: |
|
||||||
|
./build/get_external_dependencies.sh
|
||||||
|
./build/setup.sh bbb-web
|
||||||
|
tar cvf artifacts.tar artifacts/
|
||||||
|
- name: Archive packages
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: artifacts_bbb-web.tar
|
||||||
|
path: |
|
||||||
|
artifacts.tar
|
||||||
|
build-bbb-fsesl-akka:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
fetch-depth: 0 # Fetch all history
|
||||||
|
- run: echo "CACHE_AKKA_FSESL_KEY=$(git log -1 --format=%H -- akka-bbb-fsesl)" >> $GITHUB_ENV
|
||||||
|
- run: echo "CACHE_COMMON_MSG_KEY=$(git log -1 --format=%H -- bbb-common-message)" >> $GITHUB_ENV
|
||||||
|
- run: echo "CACHE_BBB_RELEASE_KEY=$(git log -1 --format=%H -- bigbluebutton-config/bigbluebutton-release)" >> $GITHUB_ENV
|
||||||
|
- run: echo "FORCE_GIT_REV=0" >> $GITHUB_ENV #used by setup.sh
|
||||||
|
- run: echo "FORCE_COMMIT_DATE=0" >> $GITHUB_ENV #used by setup.sh
|
||||||
|
- name: Handle cache
|
||||||
|
id: cache-action
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: artifacts.tar
|
||||||
|
key: ${{ runner.os }}-bbb-fsesl-akka-${{ env.CACHE_AKKA_FSESL_KEY }}-${{ env.CACHE_COMMON_MSG_KEY }}-${{ env.CACHE_BBB_RELEASE_KEY }}
|
||||||
|
- if: ${{ steps.cache-action.outputs.cache-hit != 'true' }}
|
||||||
|
name: Generate artifacts
|
||||||
|
run: |
|
||||||
|
./build/get_external_dependencies.sh
|
||||||
|
./build/setup.sh bbb-fsesl-akka
|
||||||
|
tar cvf artifacts.tar artifacts/
|
||||||
|
- name: Archive packages
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: artifacts_bbb-fsesl-akka.tar
|
||||||
|
path: |
|
||||||
|
artifacts.tar
|
||||||
|
build-bbb-html5:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
fetch-depth: 0 # Fetch all history
|
||||||
|
- run: echo "CACHE_KEY=$(git log -1 --format=%H -- bigbluebutton-html5)" >> $GITHUB_ENV
|
||||||
|
- run: echo "CACHE_BBB_RELEASE_KEY=$(git log -1 --format=%H -- bigbluebutton-config/bigbluebutton-release)" >> $GITHUB_ENV
|
||||||
|
- run: echo "FORCE_GIT_REV=0" >> $GITHUB_ENV #used by setup.sh
|
||||||
|
- run: echo "FORCE_COMMIT_DATE=0" >> $GITHUB_ENV #used by setup.sh
|
||||||
|
- name: Handle cache
|
||||||
|
id: cache-action
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: artifacts.tar
|
||||||
|
key: ${{ runner.os }}-bbb-html5-${{ env.CACHE_KEY }}-${{ env.CACHE_BBB_RELEASE_KEY }}
|
||||||
|
- if: ${{ steps.cache-action.outputs.cache-hit != 'true' }}
|
||||||
|
name: Generate artifacts
|
||||||
|
run: |
|
||||||
|
./build/get_external_dependencies.sh
|
||||||
|
./build/setup.sh bbb-html5-nodejs
|
||||||
|
./build/setup.sh bbb-html5
|
||||||
|
tar cvf artifacts.tar artifacts/
|
||||||
|
- name: Archive packages
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: artifacts_bbb-html5.tar
|
||||||
|
path: |
|
||||||
|
artifacts.tar
|
||||||
|
build-bbb-freeswitch:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
fetch-depth: 0 # Fetch all history
|
||||||
|
- run: echo "CACHE_FREESWITCH_KEY=$(git log -1 --format=%H -- build/packages-template/bbb-freeswitch-core)" >> $GITHUB_ENV
|
||||||
|
- run: echo "CACHE_FREESWITCH_SOUNDS_KEY=$(git log -1 --format=%H -- build/packages-template/bbb-freeswitch-sounds)" >> $GITHUB_ENV
|
||||||
|
- run: echo "CACHE_SOUNDS_KEY=$(curl -Is http://bigbluebutton.org/downloads/sounds.tar.gz | grep "Last-Modified" | md5sum | awk '{ print $1 }')" >> $GITHUB_ENV
|
||||||
|
- run: echo "CACHE_BBB_RELEASE_KEY=$(git log -1 --format=%H -- bigbluebutton-config/bigbluebutton-release)" >> $GITHUB_ENV
|
||||||
|
- run: echo "FORCE_GIT_REV=0" >> $GITHUB_ENV #used by setup.sh
|
||||||
|
- run: echo "FORCE_COMMIT_DATE=0" >> $GITHUB_ENV #used by setup.sh
|
||||||
|
- name: Handle cache
|
||||||
|
id: cache-action
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: artifacts.tar
|
||||||
|
key: ${{ runner.os }}-bbb-freeswitch-${{ env.CACHE_FREESWITCH_KEY }}-${{ env.CACHE_FREESWITCH_SOUNDS_KEY }}-${{ env.CACHE_SOUNDS_KEY }}-${{ env.CACHE_BBB_RELEASE_KEY }}
|
||||||
|
- if: ${{ steps.cache-action.outputs.cache-hit != 'true' }}
|
||||||
|
name: Generate artifacts
|
||||||
|
run: |
|
||||||
|
./build/get_external_dependencies.sh
|
||||||
|
./build/setup.sh bbb-freeswitch-core
|
||||||
|
./build/setup.sh bbb-freeswitch-sounds
|
||||||
|
tar cvf artifacts.tar artifacts/
|
||||||
|
- name: Archive packages
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: artifacts_bbb-freeswitch.tar
|
||||||
|
path: |
|
||||||
|
artifacts.tar
|
||||||
|
build-others:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- run: ./build/get_external_dependencies.sh
|
||||||
|
- run: echo "FORCE_GIT_REV=0" >> $GITHUB_ENV #used by setup.sh
|
||||||
|
- run: echo "FORCE_COMMIT_DATE=0" >> $GITHUB_ENV #used by setup.sh
|
||||||
|
- run: ./build/setup.sh bbb-mkclean
|
||||||
|
- run: ./build/setup.sh bbb-pads
|
||||||
|
- run: ./build/setup.sh bbb-libreoffice-docker
|
||||||
- run: ./build/setup.sh bbb-webrtc-sfu
|
- run: ./build/setup.sh bbb-webrtc-sfu
|
||||||
- run: ./build/setup.sh bbb-webrtc-recorder
|
- run: ./build/setup.sh bbb-webrtc-recorder
|
||||||
- run: ./build/setup.sh bbb-transcription-controller
|
- run: ./build/setup.sh bbb-transcription-controller
|
||||||
@ -57,37 +314,114 @@ jobs:
|
|||||||
artifacts.tar
|
artifacts.tar
|
||||||
# - name: Fake package build
|
# - name: Fake package build
|
||||||
# run: |
|
# run: |
|
||||||
# sudo sh -c '
|
# sudo -i <<EOF
|
||||||
|
# set -e
|
||||||
# echo "Faking a package build (to speed up installation test)"
|
# echo "Faking a package build (to speed up installation test)"
|
||||||
# cd /
|
# cd /
|
||||||
# wget -q "http://ci.bbb.imdt.dev/artifacts.tar"
|
# wget -nv "http://ci.bbb.imdt.dev/artifacts.tar"
|
||||||
# tar xf artifacts.tar
|
# tar xf artifacts.tar
|
||||||
# '
|
# mv artifacts /home/runner/work/bigbluebutton/bigbluebutton/artifacts/
|
||||||
|
# EOF
|
||||||
|
install-and-run-tests:
|
||||||
|
needs: [build-bbb-apps-akka, build-bbb-config, build-bbb-export-annotations, build-bbb-learning-dashboard, build-bbb-playback-record, build-bbb-graphql-server, build-bbb-etherpad, build-bbb-bbb-web, build-bbb-fsesl-akka, build-bbb-html5, build-bbb-freeswitch, build-others]
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- run: ./build/get_external_dependencies.sh
|
||||||
|
- name: Download artifacts_bbb-apps-akka
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: artifacts_bbb-apps-akka.tar
|
||||||
|
- run: tar xf artifacts.tar
|
||||||
|
- name: Download artifacts_bbb-config
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: artifacts_bbb-config.tar
|
||||||
|
- run: tar xf artifacts.tar
|
||||||
|
- name: Download artifacts_bbb-export-annotations
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: artifacts_bbb-export-annotations.tar
|
||||||
|
- run: tar xf artifacts.tar
|
||||||
|
- name: Download artifacts_bbb-learning-dashboard
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: artifacts_bbb-learning-dashboard.tar
|
||||||
|
- run: tar xf artifacts.tar
|
||||||
|
- name: Download artifacts_bbb-playback-record
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: artifacts_bbb-playback-record.tar
|
||||||
|
- run: tar xf artifacts.tar
|
||||||
|
- name: Download artifacts_bbb-graphql-server
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: artifacts_bbb-graphql-server.tar
|
||||||
|
- run: tar xf artifacts.tar
|
||||||
|
- name: Download artifacts_bbb-etherpad
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: artifacts_bbb-etherpad.tar
|
||||||
|
- run: tar xf artifacts.tar
|
||||||
|
- name: Download artifacts_bbb-freeswitch
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: artifacts_bbb-freeswitch.tar
|
||||||
|
- run: tar xf artifacts.tar
|
||||||
|
- name: Download artifacts_bbb-web
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: artifacts_bbb-web.tar
|
||||||
|
- run: tar xf artifacts.tar
|
||||||
|
- name: Download artifacts_bbb-fsesl-akka
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: artifacts_bbb-fsesl-akka.tar
|
||||||
|
- run: tar xf artifacts.tar
|
||||||
|
- name: Download artifacts_bbb-html5
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: artifacts_bbb-html5.tar
|
||||||
|
- run: tar xf artifacts.tar
|
||||||
|
- name: Download artifacts
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: artifacts.tar
|
||||||
|
- run: tar xf artifacts.tar
|
||||||
|
- name: Extracting files .tar
|
||||||
|
run: |
|
||||||
|
set -e
|
||||||
|
pwd
|
||||||
|
echo "----ls artifacts/----"
|
||||||
|
ls artifacts/
|
||||||
|
echo "Done"
|
||||||
- name: Generate CA
|
- name: Generate CA
|
||||||
run: |
|
run: |
|
||||||
sudo sh -c '
|
sudo -i <<EOF
|
||||||
|
set -e
|
||||||
mkdir /root/bbb-ci-ssl/
|
mkdir /root/bbb-ci-ssl/
|
||||||
cd /root/bbb-ci-ssl/
|
cd /root/bbb-ci-ssl/
|
||||||
openssl rand -base64 48 > /root/bbb-ci-ssl/bbb-dev-ca.pass ;
|
openssl rand -base64 48 > /root/bbb-ci-ssl/bbb-dev-ca.pass ;
|
||||||
chmod 600 /root/bbb-ci-ssl/bbb-dev-ca.pass ;
|
chmod 600 /root/bbb-ci-ssl/bbb-dev-ca.pass ;
|
||||||
openssl genrsa -des3 -out bbb-dev-ca.key -passout file:/root/bbb-ci-ssl/bbb-dev-ca.pass 2048 ;
|
openssl genrsa -des3 -out bbb-dev-ca.key -passout file:/root/bbb-ci-ssl/bbb-dev-ca.pass 2048 ;
|
||||||
openssl req -x509 -new -nodes -key bbb-dev-ca.key -sha256 -days 1460 -passin file:/root/bbb-ci-ssl/bbb-dev-ca.pass -out bbb-dev-ca.crt -subj "/C=CA/ST=BBB/L=BBB/O=BBB/OU=BBB/CN=BBB-DEV" ;
|
openssl req -x509 -new -nodes -key bbb-dev-ca.key -sha256 -days 1460 -passin file:/root/bbb-ci-ssl/bbb-dev-ca.pass -out bbb-dev-ca.crt -subj "/C=CA/ST=BBB/L=BBB/O=BBB/OU=BBB/CN=BBB-DEV" ;
|
||||||
'
|
EOF
|
||||||
- name: Trust CA
|
- name: Trust CA
|
||||||
run: |
|
run: |
|
||||||
sudo sh -c '
|
sudo -i <<EOF
|
||||||
|
set -e
|
||||||
sudo mkdir /usr/local/share/ca-certificates/bbb-dev/
|
sudo mkdir /usr/local/share/ca-certificates/bbb-dev/
|
||||||
sudo cp /root/bbb-ci-ssl/bbb-dev-ca.crt /usr/local/share/ca-certificates/bbb-dev/
|
sudo cp /root/bbb-ci-ssl/bbb-dev-ca.crt /usr/local/share/ca-certificates/bbb-dev/
|
||||||
sudo chmod 644 /usr/local/share/ca-certificates/bbb-dev/bbb-dev-ca.crt
|
sudo chmod 644 /usr/local/share/ca-certificates/bbb-dev/bbb-dev-ca.crt
|
||||||
sudo update-ca-certificates
|
sudo update-ca-certificates
|
||||||
'
|
EOF
|
||||||
- name: Generate certificate
|
- name: Generate certificate
|
||||||
run: |
|
run: |
|
||||||
sudo sh -c '
|
sudo sh -c '
|
||||||
cd /root/bbb-ci-ssl/
|
cd /root/bbb-ci-ssl/
|
||||||
echo "$(hostname -I | cut -d" " -f1) bbb-ci.test" >> /etc/hosts
|
echo "$(hostname -I | cut -d" " -f1) bbb-ci.test" >> /etc/hosts
|
||||||
openssl genrsa -out bbb-ci.test.key 2048
|
openssl genrsa -out bbb-ci.test.key 2048
|
||||||
rm bbb-ci.test.csr bbb-ci.test.crt bbb-ci.test.key
|
rm -f bbb-ci.test.csr bbb-ci.test.crt bbb-ci.test.key
|
||||||
cat > bbb-ci.test.ext << EOF
|
cat > bbb-ci.test.ext << EOF
|
||||||
authorityKeyIdentifier=keyid,issuer
|
authorityKeyIdentifier=keyid,issuer
|
||||||
basicConstraints=CA:FALSE
|
basicConstraints=CA:FALSE
|
||||||
@ -107,32 +441,33 @@ jobs:
|
|||||||
cat /root/bbb-ci-ssl/bbb-ci.test.key > /local/certs/privkey.pem
|
cat /root/bbb-ci-ssl/bbb-ci.test.key > /local/certs/privkey.pem
|
||||||
'
|
'
|
||||||
- name: Setup local repository
|
- name: Setup local repository
|
||||||
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
sudo sh -c '
|
sudo -i <<EOF
|
||||||
|
set -e
|
||||||
apt install -yq dpkg-dev
|
apt install -yq dpkg-dev
|
||||||
cd /root && wget -q http://ci.bbb.imdt.dev/cache-3rd-part-packages.tar
|
cd /root && wget -nv http://ci.bbb.imdt.dev/cache-3rd-part-packages.tar
|
||||||
cp -r /home/runner/work/bigbluebutton/bigbluebutton/artifacts/ /artifacts/
|
cp -r /home/runner/work/bigbluebutton/bigbluebutton/artifacts/ /artifacts/
|
||||||
cd /artifacts && tar xf /root/cache-3rd-part-packages.tar
|
cd /artifacts && tar xf /root/cache-3rd-part-packages.tar
|
||||||
cd /artifacts && dpkg-scanpackages . /dev/null | gzip -9c > Packages.gz
|
cd /artifacts && dpkg-scanpackages . /dev/null | gzip -9c > Packages.gz
|
||||||
echo "deb [trusted=yes] file:/artifacts/ ./" >> /etc/apt/sources.list
|
echo "deb [trusted=yes] file:/artifacts/ ./" >> /etc/apt/sources.list
|
||||||
'
|
EOF
|
||||||
- name: Prepare for install
|
- name: Prepare for install
|
||||||
run: |
|
run: |
|
||||||
sudo sh -c '
|
sudo sh -c '
|
||||||
apt --purge -y remove apache2-bin
|
apt --purge -y remove apache2-bin
|
||||||
apt-get update
|
|
||||||
DEBIAN_FRONTEND=noninteractive apt-get dist-upgrade -y
|
|
||||||
'
|
'
|
||||||
- name: Install BBB
|
- name: Install BBB
|
||||||
run: |
|
run: |
|
||||||
sudo sh -c '
|
sudo -i <<EOF
|
||||||
|
set -e
|
||||||
cd /root/ && wget -q https://raw.githubusercontent.com/bigbluebutton/bbb-install/v2.8.x-release/bbb-install.sh -O bbb-install.sh
|
cd /root/ && wget -q https://raw.githubusercontent.com/bigbluebutton/bbb-install/v2.8.x-release/bbb-install.sh -O bbb-install.sh
|
||||||
cat bbb-install.sh | sed "s|> /etc/apt/sources.list.d/bigbluebutton.list||g" | bash -s -- -v jammy-28-develop -s bbb-ci.test -j -d /certs/
|
cat bbb-install.sh | sed "s|> /etc/apt/sources.list.d/bigbluebutton.list||g" | bash -s -- -v jammy-28-develop -s bbb-ci.test -j -d /certs/
|
||||||
bbb-conf --salt bbbci
|
bbb-conf --salt bbbci
|
||||||
echo "NODE_EXTRA_CA_CERTS=/usr/local/share/ca-certificates/bbb-dev/bbb-dev-ca.crt" >> /usr/share/meteor/bundle/bbb-html5-with-roles.conf
|
echo "NODE_EXTRA_CA_CERTS=/usr/local/share/ca-certificates/bbb-dev/bbb-dev-ca.crt" >> /usr/share/meteor/bundle/bbb-html5-with-roles.conf
|
||||||
sed -i "s/\"minify\": true,/\"minify\": false,/" /usr/share/etherpad-lite/settings.json
|
sed -i "s/\"minify\": true,/\"minify\": false,/" /usr/share/etherpad-lite/settings.json
|
||||||
bbb-conf --restart
|
bbb-conf --restart
|
||||||
'
|
EOF
|
||||||
- name: Install test dependencies
|
- name: Install test dependencies
|
||||||
working-directory: ./bigbluebutton-tests/playwright
|
working-directory: ./bigbluebutton-tests/playwright
|
||||||
run: |
|
run: |
|
||||||
@ -174,7 +509,7 @@ jobs:
|
|||||||
- if: failure()
|
- if: failure()
|
||||||
name: Prepare artifacts (configs and logs)
|
name: Prepare artifacts (configs and logs)
|
||||||
run: |
|
run: |
|
||||||
sudo sh -c '
|
sudo -i <<EOF
|
||||||
mkdir configs
|
mkdir configs
|
||||||
cp /etc/haproxy/haproxy.cfg configs/haproxy.cfg
|
cp /etc/haproxy/haproxy.cfg configs/haproxy.cfg
|
||||||
touch /etc/bigbluebutton/turn-stun-servers.xml
|
touch /etc/bigbluebutton/turn-stun-servers.xml
|
||||||
@ -191,10 +526,11 @@ jobs:
|
|||||||
cp /etc/bbb-webrtc-recorder/bbb-webrtc-recorder.yml configs/bbb-webrtc-recorder-default.yml
|
cp /etc/bbb-webrtc-recorder/bbb-webrtc-recorder.yml configs/bbb-webrtc-recorder-default.yml
|
||||||
cp /usr/share/bigbluebutton/nginx/sip.nginx configs/nginx_sip.nginx
|
cp /usr/share/bigbluebutton/nginx/sip.nginx configs/nginx_sip.nginx
|
||||||
cp /etc/hosts /configs/hosts
|
cp /etc/hosts /configs/hosts
|
||||||
chmod a+r -R configs
|
mv configs /home/runner/work/bigbluebutton/bigbluebutton/configs
|
||||||
|
chmod a+r -R /home/runner/work/bigbluebutton/bigbluebutton/configs
|
||||||
bbb-conf --zip
|
bbb-conf --zip
|
||||||
cp $(ls -t /root/*.tar.gz | head -1) ./bbb-logs.tar.gz
|
ls -t /root/*.tar.gz | head -1 | xargs -I '{}' cp '{}' /home/runner/work/bigbluebutton/bigbluebutton/bbb-logs.tar.gz
|
||||||
'
|
EOF
|
||||||
- if: failure()
|
- if: failure()
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
|
@ -24,9 +24,10 @@ const TRACE_LOGS = Meteor.settings.public.kurento.traceLogs;
|
|||||||
const GATHERING_TIMEOUT = Meteor.settings.public.kurento.gatheringTimeout;
|
const GATHERING_TIMEOUT = Meteor.settings.public.kurento.gatheringTimeout;
|
||||||
const MEDIA = Meteor.settings.public.media;
|
const MEDIA = Meteor.settings.public.media;
|
||||||
const DEFAULT_FULLAUDIO_MEDIA_SERVER = MEDIA.audio.fullAudioMediaServer;
|
const DEFAULT_FULLAUDIO_MEDIA_SERVER = MEDIA.audio.fullAudioMediaServer;
|
||||||
|
const RETRY_THROUGH_RELAY = MEDIA.audio.retryThroughRelay || false;
|
||||||
const LISTEN_ONLY_OFFERING = MEDIA.listenOnlyOffering;
|
const LISTEN_ONLY_OFFERING = MEDIA.listenOnlyOffering;
|
||||||
const MEDIA_TAG = MEDIA.mediaTag.replace(/#/g, '');
|
const MEDIA_TAG = MEDIA.mediaTag.replace(/#/g, '');
|
||||||
const RECONNECT_TIMEOUT_MS = MEDIA.listenOnlyCallTimeout || 15000;
|
const CONNECTION_TIMEOUT_MS = MEDIA.listenOnlyCallTimeout || 15000;
|
||||||
const { audio: NETWORK_PRIORITY } = MEDIA.networkPriorities || {};
|
const { audio: NETWORK_PRIORITY } = MEDIA.networkPriorities || {};
|
||||||
const SENDRECV_ROLE = 'sendrecv';
|
const SENDRECV_ROLE = 'sendrecv';
|
||||||
const RECV_ROLE = 'recv';
|
const RECV_ROLE = 'recv';
|
||||||
@ -44,6 +45,9 @@ const errorCodeMap = {
|
|||||||
1307: 1007,
|
1307: 1007,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Error codes that are prone to a retry according to RETRY_THROUGH_RELAY
|
||||||
|
const RETRYABLE_ERRORS = [1007, 1010];
|
||||||
|
|
||||||
const mapErrorCode = (error) => {
|
const mapErrorCode = (error) => {
|
||||||
const { errorCode } = error;
|
const { errorCode } = error;
|
||||||
const mappedErrorCode = errorCodeMap[errorCode];
|
const mappedErrorCode = errorCodeMap[errorCode];
|
||||||
@ -76,8 +80,9 @@ export default class SFUAudioBridge extends BaseAudioBridge {
|
|||||||
this.broker = null;
|
this.broker = null;
|
||||||
this.reconnecting = false;
|
this.reconnecting = false;
|
||||||
this.iceServers = [];
|
this.iceServers = [];
|
||||||
this.inEchoTest = false;
|
|
||||||
this.bridgeName = BRIDGE_NAME;
|
this.bridgeName = BRIDGE_NAME;
|
||||||
|
|
||||||
|
this.handleTermination = this.handleTermination.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
get inputStream() {
|
get inputStream() {
|
||||||
@ -111,73 +116,104 @@ export default class SFUAudioBridge extends BaseAudioBridge {
|
|||||||
return doGUM(constraints, true);
|
return doGUM(constraints, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleTermination() {
|
setConnectionTimeout() {
|
||||||
return this.callback({ status: this.baseCallStates.ended, bridge: this.bridgeName });
|
if (this.connectionTimeout) this.clearConnectionTimeout();
|
||||||
|
|
||||||
|
this.connectionTimeout = setTimeout(() => {
|
||||||
|
const error = new Error(`ICE negotiation timeout after ${CONNECTION_TIMEOUT_MS / 1000}s`);
|
||||||
|
error.errorCode = 1010;
|
||||||
|
// Duplicating key-vals because I can'decide settle on an error pattern - prlanzarin again
|
||||||
|
error.errorCause = error.message;
|
||||||
|
error.errorMessage = error.message;
|
||||||
|
this.handleBrokerFailure(error);
|
||||||
|
}, CONNECTION_TIMEOUT_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
clearReconnectionTimeout() {
|
clearConnectionTimeout() {
|
||||||
this.reconnecting = false;
|
if (this.connectionTimeout) {
|
||||||
if (this.reconnectionTimeout) {
|
clearTimeout(this.connectionTimeout);
|
||||||
clearTimeout(this.reconnectionTimeout);
|
this.connectionTimeout = null;
|
||||||
this.reconnectionTimeout = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
reconnect() {
|
dispatchAutoplayHandlingEvent(mediaElement) {
|
||||||
this.broker.stop();
|
const tagFailedEvent = new CustomEvent('audioPlayFailed', {
|
||||||
this.callback({ status: this.baseCallStates.reconnecting, bridge: this.bridgeName });
|
detail: { mediaElement },
|
||||||
this.reconnecting = true;
|
|
||||||
// Set up a reconnectionTimeout in case the server is unresponsive
|
|
||||||
// for some reason. If it gets triggered, end the session and stop
|
|
||||||
// trying to reconnect
|
|
||||||
this.reconnectionTimeout = setTimeout(() => {
|
|
||||||
this.callback({
|
|
||||||
status: this.baseCallStates.failed,
|
|
||||||
error: 1010,
|
|
||||||
bridgeError: 'Reconnection timeout',
|
|
||||||
bridge: this.bridgeName,
|
|
||||||
});
|
|
||||||
this.broker.stop();
|
|
||||||
this.clearReconnectionTimeout();
|
|
||||||
}, RECONNECT_TIMEOUT_MS);
|
|
||||||
|
|
||||||
this.joinAudio({ isListenOnly: this.isListenOnly }, this.callback).then(
|
|
||||||
() => this.clearReconnectionTimeout(),
|
|
||||||
).catch((error) => {
|
|
||||||
// Error handling is a no-op because it will be "handled" in handleBrokerFailure
|
|
||||||
logger.debug({
|
|
||||||
logCode: 'sfuaudio_reconnect_failed',
|
|
||||||
extraInfo: {
|
|
||||||
errorMessage: error.errorMessage,
|
|
||||||
reconnecting: this.reconnecting,
|
|
||||||
bridge: this.bridgeName,
|
|
||||||
role: this.role,
|
|
||||||
},
|
|
||||||
}, 'SFU audio reconnect failed');
|
|
||||||
});
|
});
|
||||||
|
window.dispatchEvent(tagFailedEvent);
|
||||||
|
this.callback({ status: this.baseCallStates.autoplayBlocked, bridge: this.bridgeName });
|
||||||
|
}
|
||||||
|
|
||||||
|
reconnect(options = {}) {
|
||||||
|
// If broker has already started, fire the reconnecting callback so the user
|
||||||
|
// knows what's going on
|
||||||
|
if (this.broker.started) {
|
||||||
|
this.callback({ status: this.baseCallStates.reconnecting, bridge: this.bridgeName });
|
||||||
|
} else {
|
||||||
|
// Otherwise: override termination handler so the ended callback doesn't get
|
||||||
|
// triggered - this is a retry attempt and the user shouldn't be notified
|
||||||
|
// yet.
|
||||||
|
this.broker.onended = () => {};
|
||||||
|
}
|
||||||
|
|
||||||
|
this.broker.stop();
|
||||||
|
this.reconnecting = true;
|
||||||
|
this._startBroker({ isListenOnly: this.isListenOnly, ...options })
|
||||||
|
.catch((error) => {
|
||||||
|
// Error handling is a no-op because it will be "handled" in handleBrokerFailure
|
||||||
|
logger.debug({
|
||||||
|
logCode: 'sfuaudio_reconnect_failed',
|
||||||
|
extraInfo: {
|
||||||
|
errorMessage: error.errorMessage,
|
||||||
|
reconnecting: this.reconnecting,
|
||||||
|
bridge: this.bridgeName,
|
||||||
|
role: this.role,
|
||||||
|
},
|
||||||
|
}, 'SFU audio reconnect failed');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
handleBrokerFailure(error) {
|
handleBrokerFailure(error) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
this.clearConnectionTimeout();
|
||||||
mapErrorCode(error);
|
mapErrorCode(error);
|
||||||
const { errorMessage, errorCause, errorCode } = error;
|
const { errorMessage, errorCause, errorCode } = error;
|
||||||
|
|
||||||
if (this.broker.started && !this.reconnecting) {
|
if (!this.reconnecting) {
|
||||||
logger.error({
|
if (this.broker.started) {
|
||||||
logCode: 'sfuaudio_error_try_to_reconnect',
|
logger.error({
|
||||||
extraInfo: {
|
logCode: 'sfuaudio_error_try_to_reconnect',
|
||||||
errorMessage,
|
extraInfo: {
|
||||||
errorCode,
|
errorMessage,
|
||||||
errorCause,
|
errorCode,
|
||||||
bridge: this.bridgeName,
|
errorCause,
|
||||||
role: this.role,
|
bridge: this.bridgeName,
|
||||||
},
|
role: this.role,
|
||||||
}, 'SFU audio failed, try to reconnect');
|
},
|
||||||
this.reconnect();
|
}, 'SFU audio failed, try to reconnect');
|
||||||
return resolve();
|
this.reconnect();
|
||||||
|
return resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RETRYABLE_ERRORS.includes(errorCode) && RETRY_THROUGH_RELAY) {
|
||||||
|
logger.error({
|
||||||
|
logCode: 'sfuaudio_error_retry_through_relay',
|
||||||
|
extraInfo: {
|
||||||
|
errorMessage,
|
||||||
|
errorCode,
|
||||||
|
errorCause,
|
||||||
|
bridge: this.bridgeName,
|
||||||
|
role: this.role,
|
||||||
|
},
|
||||||
|
}, 'SFU audio failed to connect, retry through relay');
|
||||||
|
this.reconnect({ forceRelay: true });
|
||||||
|
return resolve();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Already tried reconnecting once OR the user handn't succesfully
|
// Already tried reconnecting once OR the user handn't succesfully
|
||||||
// connected firsthand. Just finish the session and reject with error
|
// connected firsthand and retrying isn't an option. Finish the session
|
||||||
|
// and reject with the error
|
||||||
logger.error({
|
logger.error({
|
||||||
logCode: 'sfuaudio_error',
|
logCode: 'sfuaudio_error',
|
||||||
extraInfo: {
|
extraInfo: {
|
||||||
@ -189,7 +225,7 @@ export default class SFUAudioBridge extends BaseAudioBridge {
|
|||||||
role: this.role,
|
role: this.role,
|
||||||
},
|
},
|
||||||
}, 'SFU audio failed');
|
}, 'SFU audio failed');
|
||||||
this.clearReconnectionTimeout();
|
this.clearConnectionTimeout();
|
||||||
this.broker.stop();
|
this.broker.stop();
|
||||||
this.callback({
|
this.callback({
|
||||||
status: this.baseCallStates.failed,
|
status: this.baseCallStates.failed,
|
||||||
@ -201,23 +237,23 @@ export default class SFUAudioBridge extends BaseAudioBridge {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatchAutoplayHandlingEvent(mediaElement) {
|
handleTermination() {
|
||||||
const tagFailedEvent = new CustomEvent('audioPlayFailed', {
|
this.clearConnectionTimeout();
|
||||||
detail: { mediaElement },
|
return this.callback({ status: this.baseCallStates.ended, bridge: this.bridgeName });
|
||||||
});
|
|
||||||
window.dispatchEvent(tagFailedEvent);
|
|
||||||
this.callback({ status: this.baseCallStates.autoplayBlocked, bridge: this.bridgeName });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleStart() {
|
handleStart() {
|
||||||
const stream = this.broker.webRtcPeer.getRemoteStream();
|
const stream = this.broker.webRtcPeer.getRemoteStream();
|
||||||
const mediaElement = document.getElementById(MEDIA_TAG);
|
const mediaElement = document.getElementById(MEDIA_TAG);
|
||||||
|
|
||||||
return loadAndPlayMediaStream(stream, mediaElement, false).then(() => this
|
return loadAndPlayMediaStream(stream, mediaElement, false).then(() => {
|
||||||
.callback({
|
this.callback({
|
||||||
status: this.baseCallStates.started,
|
status: this.baseCallStates.started,
|
||||||
bridge: this.bridgeName,
|
bridge: this.bridgeName,
|
||||||
})).catch((error) => {
|
});
|
||||||
|
this.clearConnectionTimeout();
|
||||||
|
this.reconnecting = false;
|
||||||
|
}).catch((error) => {
|
||||||
// NotAllowedError equals autoplay issues, fire autoplay handling event.
|
// NotAllowedError equals autoplay issues, fire autoplay handling event.
|
||||||
// This will be handled in audio-manager.
|
// This will be handled in audio-manager.
|
||||||
if (error.name === 'NotAllowedError') {
|
if (error.name === 'NotAllowedError') {
|
||||||
@ -247,9 +283,32 @@ export default class SFUAudioBridge extends BaseAudioBridge {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async _startBroker(options) {
|
async _startBroker(options) {
|
||||||
|
try {
|
||||||
|
this.iceServers = await fetchWebRTCMappedStunTurnServers(this.sessionToken);
|
||||||
|
} catch (error) {
|
||||||
|
logger.error({ logCode: 'sfuaudio_stun-turn_fetch_failed' },
|
||||||
|
'SFU audio bridge failed to fetch STUN/TURN info, using default servers');
|
||||||
|
this.iceServers = getMappedFallbackStun();
|
||||||
|
}
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
const {
|
||||||
|
isListenOnly,
|
||||||
|
extension,
|
||||||
|
inputStream,
|
||||||
|
forceRelay: _forceRelay = false,
|
||||||
|
} = options;
|
||||||
|
|
||||||
|
const handleInitError = (_error) => {
|
||||||
|
mapErrorCode(_error);
|
||||||
|
if (RETRYABLE_ERRORS.includes(_error?.errorCode)
|
||||||
|
|| !RETRY_THROUGH_RELAY
|
||||||
|
|| this.reconnecting) {
|
||||||
|
reject(_error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { isListenOnly, extension, inputStream } = options;
|
|
||||||
this.inEchoTest = !!extension;
|
this.inEchoTest = !!extension;
|
||||||
this.isListenOnly = isListenOnly;
|
this.isListenOnly = isListenOnly;
|
||||||
|
|
||||||
@ -259,7 +318,7 @@ export default class SFUAudioBridge extends BaseAudioBridge {
|
|||||||
iceServers: this.iceServers,
|
iceServers: this.iceServers,
|
||||||
mediaServer: getMediaServerAdapter(isListenOnly),
|
mediaServer: getMediaServerAdapter(isListenOnly),
|
||||||
constraints: getAudioConstraints({ deviceId: this.inputDeviceId }),
|
constraints: getAudioConstraints({ deviceId: this.inputDeviceId }),
|
||||||
forceRelay: shouldForceRelay(),
|
forceRelay: _forceRelay || shouldForceRelay(),
|
||||||
stream: (inputStream && inputStream.active) ? inputStream : undefined,
|
stream: (inputStream && inputStream.active) ? inputStream : undefined,
|
||||||
offering: isListenOnly ? LISTEN_ONLY_OFFERING : true,
|
offering: isListenOnly ? LISTEN_ONLY_OFFERING : true,
|
||||||
signalCandidates: SIGNAL_CANDIDATES,
|
signalCandidates: SIGNAL_CANDIDATES,
|
||||||
@ -283,25 +342,19 @@ export default class SFUAudioBridge extends BaseAudioBridge {
|
|||||||
this.handleStart().then(resolve).catch(reject);
|
this.handleStart().then(resolve).catch(reject);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.broker.joinAudio().catch(reject);
|
// Set up a connectionTimeout in case the server or network are botching
|
||||||
|
// negotiation or conn checks.
|
||||||
|
this.setConnectionTimeout();
|
||||||
|
this.broker.joinAudio().catch(handleInitError);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.warn({ logCode: 'sfuaudio_bridge_broker_init_fail' },
|
handleInitError(error);
|
||||||
'Problem when initializing SFU broker for fullaudio bridge');
|
|
||||||
reject(error);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async joinAudio(options, callback) {
|
async joinAudio(options, callback) {
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
|
this.reconnecting = false;
|
||||||
try {
|
|
||||||
this.iceServers = await fetchWebRTCMappedStunTurnServers(this.sessionToken);
|
|
||||||
} catch (error) {
|
|
||||||
logger.error({ logCode: 'sfuaudio_stun-turn_fetch_failed' },
|
|
||||||
'SFU audio bridge failed to fetch STUN/TURN info, using default servers');
|
|
||||||
this.iceServers = getMappedFallbackStun();
|
|
||||||
}
|
|
||||||
|
|
||||||
return this._startBroker(options);
|
return this._startBroker(options);
|
||||||
}
|
}
|
||||||
@ -390,7 +443,8 @@ export default class SFUAudioBridge extends BaseAudioBridge {
|
|||||||
exitAudio() {
|
exitAudio() {
|
||||||
const mediaElement = document.getElementById(MEDIA_TAG);
|
const mediaElement = document.getElementById(MEDIA_TAG);
|
||||||
|
|
||||||
this.clearReconnectionTimeout();
|
this.clearConnectionTimeout();
|
||||||
|
this.reconnecting = false;
|
||||||
|
|
||||||
if (this.broker) {
|
if (this.broker) {
|
||||||
this.broker.stop();
|
this.broker.stop();
|
||||||
|
@ -142,6 +142,7 @@ const IsTalkingWrapper = styled.div`
|
|||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
margin-top: 0.5rem;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Speaking = styled.div`
|
const Speaking = styled.div`
|
||||||
|
@ -20,7 +20,8 @@ import { isPresentationEnabled } from '/imports/ui/services/features';
|
|||||||
|
|
||||||
const { isMobile } = deviceInfo;
|
const { isMobile } = deviceInfo;
|
||||||
const propTypes = {
|
const propTypes = {
|
||||||
allowDownloadable: PropTypes.bool.isRequired,
|
allowDownloadOriginal: PropTypes.bool.isRequired,
|
||||||
|
allowDownloadWithAnnotations: PropTypes.bool.isRequired,
|
||||||
intl: PropTypes.shape({
|
intl: PropTypes.shape({
|
||||||
formatMessage: PropTypes.func.isRequired,
|
formatMessage: PropTypes.func.isRequired,
|
||||||
}).isRequired,
|
}).isRequired,
|
||||||
@ -804,7 +805,7 @@ class PresentationUploader extends Component {
|
|||||||
|
|
||||||
renderPresentationList() {
|
renderPresentationList() {
|
||||||
const { presentations } = this.state;
|
const { presentations } = this.state;
|
||||||
const { intl, allowDownloadable } = this.props;
|
const { intl } = this.props;
|
||||||
|
|
||||||
let presentationsSorted = presentations;
|
let presentationsSorted = presentations;
|
||||||
|
|
||||||
@ -846,9 +847,7 @@ class PresentationUploader extends Component {
|
|||||||
</tr>
|
</tr>
|
||||||
<Styled.Head>
|
<Styled.Head>
|
||||||
<th colSpan={4}>{intl.formatMessage(intlMessages.currentLabel)}</th>
|
<th colSpan={4}>{intl.formatMessage(intlMessages.currentLabel)}</th>
|
||||||
{
|
<th>{intl.formatMessage(intlMessages.actionsLabel)}</th>
|
||||||
allowDownloadable ? <th>{intl.formatMessage(intlMessages.actionsLabel)}</th> : null
|
|
||||||
}
|
|
||||||
</Styled.Head>
|
</Styled.Head>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@ -978,10 +977,10 @@ class PresentationUploader extends Component {
|
|||||||
renderDownloadableWithAnnotationsHint() {
|
renderDownloadableWithAnnotationsHint() {
|
||||||
const {
|
const {
|
||||||
intl,
|
intl,
|
||||||
allowDownloadable,
|
allowDownloadWithAnnotations,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
return allowDownloadable ? (
|
return allowDownloadWithAnnotations ? (
|
||||||
<Styled.ExportHint>
|
<Styled.ExportHint>
|
||||||
{intl.formatMessage(intlMessages.exportHint)}
|
{intl.formatMessage(intlMessages.exportHint)}
|
||||||
</Styled.ExportHint>
|
</Styled.ExportHint>
|
||||||
@ -994,7 +993,8 @@ class PresentationUploader extends Component {
|
|||||||
const {
|
const {
|
||||||
intl,
|
intl,
|
||||||
selectedToBeNextCurrent,
|
selectedToBeNextCurrent,
|
||||||
allowDownloadable,
|
allowDownloadOriginal,
|
||||||
|
allowDownloadWithAnnotations,
|
||||||
renderPresentationItemStatus,
|
renderPresentationItemStatus,
|
||||||
hasAnnotations,
|
hasAnnotations,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
@ -1068,8 +1068,8 @@ class PresentationUploader extends Component {
|
|||||||
</Styled.TableItemStatus>
|
</Styled.TableItemStatus>
|
||||||
{
|
{
|
||||||
hasError ? null : (
|
hasError ? null : (
|
||||||
<Styled.TableItemActions notDownloadable={!allowDownloadable}>
|
<Styled.TableItemActions notDownloadable={!allowDownloadOriginal}>
|
||||||
{allowDownloadable ? (
|
{allowDownloadOriginal || allowDownloadWithAnnotations ? (
|
||||||
<PresentationDownloadDropdown
|
<PresentationDownloadDropdown
|
||||||
hasAnnotations={hasAnyAnnotation}
|
hasAnnotations={hasAnyAnnotation}
|
||||||
disabled={shouldDisableExportButton}
|
disabled={shouldDisableExportButton}
|
||||||
@ -1077,6 +1077,8 @@ class PresentationUploader extends Component {
|
|||||||
aria-label={formattedDownloadAriaLabel}
|
aria-label={formattedDownloadAriaLabel}
|
||||||
color="primary"
|
color="primary"
|
||||||
isDownloadable={isDownloadable}
|
isDownloadable={isDownloadable}
|
||||||
|
allowDownloadOriginal={allowDownloadOriginal}
|
||||||
|
allowDownloadWithAnnotations={allowDownloadWithAnnotations}
|
||||||
handleToggleDownloadable={this.handleToggleDownloadable}
|
handleToggleDownloadable={this.handleToggleDownloadable}
|
||||||
item={item}
|
item={item}
|
||||||
closeModal={() => Session.set('showUploadPresentationView', false)}
|
closeModal={() => Session.set('showUploadPresentationView', false)}
|
||||||
|
@ -8,7 +8,11 @@ import PresUploaderToast from '/imports/ui/components/presentation/presentation-
|
|||||||
import PresentationUploader from './component';
|
import PresentationUploader from './component';
|
||||||
import { UsersContext } from '/imports/ui/components/components-data/users-context/context';
|
import { UsersContext } from '/imports/ui/components/components-data/users-context/context';
|
||||||
import Auth from '/imports/ui/services/auth';
|
import Auth from '/imports/ui/services/auth';
|
||||||
import { isDownloadPresentationWithAnnotationsEnabled, isPresentationEnabled } from '/imports/ui/services/features';
|
import {
|
||||||
|
isDownloadPresentationWithAnnotationsEnabled,
|
||||||
|
isDownloadOriginalPresentationEnabled,
|
||||||
|
isPresentationEnabled,
|
||||||
|
} from '/imports/ui/services/features';
|
||||||
import { hasAnnotations } from '/imports/ui/components/whiteboard/service';
|
import { hasAnnotations } from '/imports/ui/components/whiteboard/service';
|
||||||
|
|
||||||
const PRESENTATION_CONFIG = Meteor.settings.public.presentation;
|
const PRESENTATION_CONFIG = Meteor.settings.public.presentation;
|
||||||
@ -44,7 +48,8 @@ export default withTracker(() => {
|
|||||||
fileSizeMax: PRESENTATION_CONFIG.mirroredFromBBBCore.uploadSizeMax,
|
fileSizeMax: PRESENTATION_CONFIG.mirroredFromBBBCore.uploadSizeMax,
|
||||||
filePagesMax: PRESENTATION_CONFIG.mirroredFromBBBCore.uploadPagesMax,
|
filePagesMax: PRESENTATION_CONFIG.mirroredFromBBBCore.uploadPagesMax,
|
||||||
fileValidMimeTypes: PRESENTATION_CONFIG.uploadValidMimeTypes,
|
fileValidMimeTypes: PRESENTATION_CONFIG.uploadValidMimeTypes,
|
||||||
allowDownloadable: isDownloadPresentationWithAnnotationsEnabled(),
|
allowDownloadOriginal: isDownloadOriginalPresentationEnabled(),
|
||||||
|
allowDownloadWithAnnotations: isDownloadPresentationWithAnnotationsEnabled(),
|
||||||
handleSave: Service.handleSavePresentation,
|
handleSave: Service.handleSavePresentation,
|
||||||
handleDismissToast: PresUploaderToast.handleDismissToast,
|
handleDismissToast: PresUploaderToast.handleDismissToast,
|
||||||
renderToastList: Service.renderToastList,
|
renderToastList: Service.renderToastList,
|
||||||
|
@ -74,6 +74,8 @@ class PresentationDownloadDropdown extends PureComponent {
|
|||||||
handleDownloadingOfPresentation,
|
handleDownloadingOfPresentation,
|
||||||
handleToggleDownloadable,
|
handleToggleDownloadable,
|
||||||
isDownloadable,
|
isDownloadable,
|
||||||
|
allowDownloadOriginal,
|
||||||
|
allowDownloadWithAnnotations,
|
||||||
item,
|
item,
|
||||||
closeModal,
|
closeModal,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
@ -88,31 +90,35 @@ class PresentationDownloadDropdown extends PureComponent {
|
|||||||
closeModal();
|
closeModal();
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!isDownloadable) {
|
if (allowDownloadOriginal) {
|
||||||
|
if (!isDownloadable) {
|
||||||
|
this.menuItems.push({
|
||||||
|
key: this.actionsKey[0],
|
||||||
|
dataTest: 'enableOriginalPresentationDownload',
|
||||||
|
label: intl.formatMessage(intlMessages.enableOriginalPresentationDownload),
|
||||||
|
onClick: () => toggleDownloadOriginalPresentation(true),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.menuItems.push({
|
||||||
|
key: this.actionsKey[0],
|
||||||
|
dataTest: 'disableOriginalPresentationDownload',
|
||||||
|
label: intl.formatMessage(intlMessages.disableOriginalPresentationDownload),
|
||||||
|
onClick: () => toggleDownloadOriginalPresentation(false),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (allowDownloadWithAnnotations) {
|
||||||
this.menuItems.push({
|
this.menuItems.push({
|
||||||
key: this.actionsKey[0],
|
key: this.actionsKey[1],
|
||||||
dataTest: 'enableOriginalPresentationDownload',
|
id: 'sendCurrentStateDocument',
|
||||||
label: intl.formatMessage(intlMessages.enableOriginalPresentationDownload),
|
dataTest: 'sendCurrentStateDocument',
|
||||||
onClick: () => toggleDownloadOriginalPresentation(true),
|
label: intl.formatMessage(intlMessages.sendCurrentStateDocument),
|
||||||
});
|
onClick: () => {
|
||||||
} else {
|
closeModal();
|
||||||
this.menuItems.push({
|
handleDownloadingOfPresentation('Annotated');
|
||||||
key: this.actionsKey[0],
|
},
|
||||||
dataTest: 'disableOriginalPresentationDownload',
|
|
||||||
label: intl.formatMessage(intlMessages.disableOriginalPresentationDownload),
|
|
||||||
onClick: () => toggleDownloadOriginalPresentation(false),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.menuItems.push({
|
|
||||||
key: this.actionsKey[1],
|
|
||||||
id: 'sendCurrentStateDocument',
|
|
||||||
dataTest: 'sendCurrentStateDocument',
|
|
||||||
label: intl.formatMessage(intlMessages.sendCurrentStateDocument),
|
|
||||||
onClick: () => {
|
|
||||||
closeModal();
|
|
||||||
handleDownloadingOfPresentation('Annotated');
|
|
||||||
},
|
|
||||||
});
|
|
||||||
return this.menuItems;
|
return this.menuItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ const TimerWrapper = styled.div`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const Timer = styled.div`
|
const Timer = styled.div`
|
||||||
|
margin-top: 0.5rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
max-height: ${timerPaddingXL});
|
max-height: ${timerPaddingXL});
|
||||||
`;
|
`;
|
||||||
|
@ -80,7 +80,7 @@ const UserAvatar = ({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
||||||
<Styled.Talking talking={talking && !muted && avatar.length === 0} animations={animations} />
|
<Styled.Talking talking={talking && !muted} animations={animations} />
|
||||||
|
|
||||||
{avatar.length !== 0 && !emoji
|
{avatar.length !== 0 && !emoji
|
||||||
? (
|
? (
|
||||||
|
@ -34,6 +34,11 @@ const Image = styled.div`
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Img = styled.img`
|
const Img = styled.img`
|
||||||
|
@ -2,6 +2,7 @@ import React, { PureComponent } from 'react';
|
|||||||
import { defineMessages, injectIntl } from 'react-intl';
|
import { defineMessages, injectIntl } from 'react-intl';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import Styled from './styles';
|
import Styled from './styles';
|
||||||
|
import { notify } from '/imports/ui/services/notification';
|
||||||
|
|
||||||
const ASK_MODERATOR = 'ASK_MODERATOR';
|
const ASK_MODERATOR = 'ASK_MODERATOR';
|
||||||
const ALWAYS_ACCEPT = 'ALWAYS_ACCEPT';
|
const ALWAYS_ACCEPT = 'ALWAYS_ACCEPT';
|
||||||
@ -36,6 +37,10 @@ const intlMessages = defineMessages({
|
|||||||
id: 'app.guest-policy.button.alwaysDeny',
|
id: 'app.guest-policy.button.alwaysDeny',
|
||||||
description: 'Always deny button label',
|
description: 'Always deny button label',
|
||||||
},
|
},
|
||||||
|
feedbackMessage: {
|
||||||
|
id: 'app.guest-policy.feedbackMessage',
|
||||||
|
description: 'Feedback message for guest policy change',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const propTypes = {
|
const propTypes = {
|
||||||
@ -47,18 +52,31 @@ const propTypes = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class GuestPolicyComponent extends PureComponent {
|
class GuestPolicyComponent extends PureComponent {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.handleChangePolicy = this.handleChangePolicy.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
const { setIsOpen } = this.props;
|
const { setIsOpen } = this.props;
|
||||||
|
|
||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleChangePolicy(policyRule, messageId) {
|
||||||
|
const { intl, changeGuestPolicy } = this.props;
|
||||||
|
|
||||||
|
changeGuestPolicy(policyRule);
|
||||||
|
|
||||||
|
notify(intl.formatMessage(intlMessages.feedbackMessage) + intl.formatMessage(messageId), 'success');
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
setIsOpen,
|
setIsOpen,
|
||||||
intl,
|
intl,
|
||||||
guestPolicy,
|
guestPolicy,
|
||||||
changeGuestPolicy,
|
|
||||||
isOpen,
|
isOpen,
|
||||||
onRequestClose,
|
onRequestClose,
|
||||||
priority,
|
priority,
|
||||||
@ -91,7 +109,7 @@ class GuestPolicyComponent extends PureComponent {
|
|||||||
aria-pressed={guestPolicy === ASK_MODERATOR}
|
aria-pressed={guestPolicy === ASK_MODERATOR}
|
||||||
data-test="askModerator"
|
data-test="askModerator"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
changeGuestPolicy(ASK_MODERATOR);
|
this.handleChangePolicy(ASK_MODERATOR, intlMessages.askModerator);
|
||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@ -103,7 +121,7 @@ class GuestPolicyComponent extends PureComponent {
|
|||||||
aria-pressed={guestPolicy === ALWAYS_ACCEPT}
|
aria-pressed={guestPolicy === ALWAYS_ACCEPT}
|
||||||
data-test="alwaysAccept"
|
data-test="alwaysAccept"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
changeGuestPolicy(ALWAYS_ACCEPT);
|
this.handleChangePolicy(ALWAYS_ACCEPT, intlMessages.alwaysAccept);
|
||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@ -115,7 +133,7 @@ class GuestPolicyComponent extends PureComponent {
|
|||||||
aria-pressed={guestPolicy === ALWAYS_DENY}
|
aria-pressed={guestPolicy === ALWAYS_DENY}
|
||||||
data-test="alwaysDeny"
|
data-test="alwaysDeny"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
changeGuestPolicy(ALWAYS_DENY);
|
this.handleChangePolicy(ALWAYS_DENY, intlMessages.alwaysDeny);
|
||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
@ -61,7 +61,11 @@ export function isCustomVirtualBackgroundsEnabled() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function isDownloadPresentationWithAnnotationsEnabled() {
|
export function isDownloadPresentationWithAnnotationsEnabled() {
|
||||||
return getDisabledFeatures().indexOf('downloadPresentationWithAnnotations') === -1 && Meteor.settings.public.presentation.allowDownloadable;
|
return getDisabledFeatures().indexOf('downloadPresentationWithAnnotations') === -1 && Meteor.settings.public.presentation.allowDownloadWithAnnotations;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isDownloadOriginalPresentationEnabled() {
|
||||||
|
return getDisabledFeatures().indexOf('downloadOriginalPresentation') === -1 && Meteor.settings.public.presentation.allowDownloadOriginal;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isSnapshotOfCurrentSlideEnabled() {
|
export function isSnapshotOfCurrentSlideEnabled() {
|
||||||
|
@ -65,7 +65,7 @@ public:
|
|||||||
allowUserLookup: false
|
allowUserLookup: false
|
||||||
dynamicGuestPolicy: true
|
dynamicGuestPolicy: true
|
||||||
enableGuestLobbyMessage: true
|
enableGuestLobbyMessage: true
|
||||||
guestPolicyExtraAllowOptions: true
|
guestPolicyExtraAllowOptions: false
|
||||||
alwaysShowWaitingRoomUI: true
|
alwaysShowWaitingRoomUI: true
|
||||||
enableLimitOfViewersInWebcam: false
|
enableLimitOfViewersInWebcam: false
|
||||||
enableMultipleCameras: true
|
enableMultipleCameras: true
|
||||||
@ -169,7 +169,7 @@ public:
|
|||||||
enableCopyNetworkStatsButton: true
|
enableCopyNetworkStatsButton: true
|
||||||
# where should client settings be stored? if you run a single BBB server or
|
# where should client settings be stored? if you run a single BBB server or
|
||||||
# a cluster with a reverse proxy in front of it, you may set this to 'local'
|
# a cluster with a reverse proxy in front of it, you may set this to 'local'
|
||||||
# See https://docs.bigbluebutton.org/administration/cluster-proxy
|
# See See https://docs.bigbluebutton.org/administration/cluster-proxy
|
||||||
# allowed values:
|
# allowed values:
|
||||||
# 'session' -> settings are stored in browser sessionStorage
|
# 'session' -> settings are stored in browser sessionStorage
|
||||||
# 'local' -> settings are stored in browser localStorage
|
# 'local' -> settings are stored in browser localStorage
|
||||||
@ -563,7 +563,7 @@ public:
|
|||||||
type_private: PRIVATE_ACCESS
|
type_private: PRIVATE_ACCESS
|
||||||
system_userid: SYSTEM_MESSAGE
|
system_userid: SYSTEM_MESSAGE
|
||||||
system_username: SYSTEM_MESSAGE
|
system_username: SYSTEM_MESSAGE
|
||||||
public_id: MAIN-PUBLIC-GROUP-CHAT
|
public_id: public
|
||||||
public_group_id: MAIN-PUBLIC-GROUP-CHAT
|
public_group_id: MAIN-PUBLIC-GROUP-CHAT
|
||||||
public_userid: public_chat_userid
|
public_userid: public_chat_userid
|
||||||
public_username: public_chat_username
|
public_username: public_chat_username
|
||||||
@ -639,6 +639,9 @@ public:
|
|||||||
path: 'bridge/sip'
|
path: 'bridge/sip'
|
||||||
- name: fullaudio
|
- name: fullaudio
|
||||||
path: 'bridge/sfu-audio-bridge'
|
path: 'bridge/sfu-audio-bridge'
|
||||||
|
# Forces a retry with iceTransportPolicy = 'relay' if the first attempt
|
||||||
|
# fails with a few selected errors codes (eg 1007, 1010)
|
||||||
|
retryThroughRelay: false
|
||||||
stunTurnServersFetchAddress: '/bigbluebutton/api/stuns'
|
stunTurnServersFetchAddress: '/bigbluebutton/api/stuns'
|
||||||
cacheStunTurnServers: true
|
cacheStunTurnServers: true
|
||||||
fallbackStunServer: ''
|
fallbackStunServer: ''
|
||||||
@ -653,7 +656,7 @@ public:
|
|||||||
callHangupTimeout: 2000
|
callHangupTimeout: 2000
|
||||||
callHangupMaximumRetries: 10
|
callHangupMaximumRetries: 10
|
||||||
echoTestNumber: 'echo'
|
echoTestNumber: 'echo'
|
||||||
listenOnlyCallTimeout: 25000
|
listenOnlyCallTimeout: 15000
|
||||||
# Experimental. True is the canonical behavior. Flip to false to reverse
|
# Experimental. True is the canonical behavior. Flip to false to reverse
|
||||||
# the negotiation flow for LO subscribers.
|
# the negotiation flow for LO subscribers.
|
||||||
listenOnlyOffering: false
|
listenOnlyOffering: false
|
||||||
@ -742,7 +745,8 @@ public:
|
|||||||
- critical
|
- critical
|
||||||
help: STATS_HELP_URL
|
help: STATS_HELP_URL
|
||||||
presentation:
|
presentation:
|
||||||
allowDownloadable: true
|
allowDownloadOriginal: true
|
||||||
|
allowDownloadWithAnnotations: true
|
||||||
allowSnapshotOfCurrentSlide: true
|
allowSnapshotOfCurrentSlide: true
|
||||||
panZoomThrottle: 32
|
panZoomThrottle: 32
|
||||||
restoreOnUpdate: true
|
restoreOnUpdate: true
|
||||||
|
@ -288,7 +288,7 @@
|
|||||||
"app.presentationUploader.sent": "Sent",
|
"app.presentationUploader.sent": "Sent",
|
||||||
"app.presentationUploader.exportingTimeout": "The export is taking too long...",
|
"app.presentationUploader.exportingTimeout": "The export is taking too long...",
|
||||||
"app.presentationUploader.export": "Send to chat",
|
"app.presentationUploader.export": "Send to chat",
|
||||||
"app.presentationUploader.exportCurrentStatePresentation": "Send out a download link for the presentation in the current state of it",
|
"app.presentationUploader.exportCurrentStatePresentation": "Send out a download link for the presentation in its current state",
|
||||||
"app.presentationUploader.enableOriginalPresentationDownload": "Enable download of the original presentation",
|
"app.presentationUploader.enableOriginalPresentationDownload": "Enable download of the original presentation",
|
||||||
"app.presentationUploader.disableOriginalPresentationDownload": "Disable download of the original presentation",
|
"app.presentationUploader.disableOriginalPresentationDownload": "Disable download of the original presentation",
|
||||||
"app.presentationUploader.dropdownExportOptions": "Export options",
|
"app.presentationUploader.dropdownExportOptions": "Export options",
|
||||||
@ -969,6 +969,7 @@
|
|||||||
"app.guest-policy.button.alwaysAccept": "Always accept",
|
"app.guest-policy.button.alwaysAccept": "Always accept",
|
||||||
"app.guest-policy.button.alwaysDeny": "Always deny",
|
"app.guest-policy.button.alwaysDeny": "Always deny",
|
||||||
"app.guest-policy.policyBtnDesc": "Sets meeting guest policy",
|
"app.guest-policy.policyBtnDesc": "Sets meeting guest policy",
|
||||||
|
"app.guest-policy.feedbackMessage": "The guest policy is now: ",
|
||||||
"app.connection-status.ariaTitle": "Connection status modal",
|
"app.connection-status.ariaTitle": "Connection status modal",
|
||||||
"app.connection-status.title": "Connection status",
|
"app.connection-status.title": "Connection status",
|
||||||
"app.connection-status.description": "View users' connection status",
|
"app.connection-status.description": "View users' connection status",
|
||||||
|
@ -28,7 +28,8 @@ async function generateSettingsData(page) {
|
|||||||
pollEnabled: settingsData.poll.enabled,
|
pollEnabled: settingsData.poll.enabled,
|
||||||
pollChatMessage: settingsData.poll.chatMessage,
|
pollChatMessage: settingsData.poll.chatMessage,
|
||||||
// Presentation
|
// Presentation
|
||||||
presentationDownloadable: settingsData.presentation.allowDownloadable,
|
originalPresentationDownloadable: settingsData.presentation.allowDownloadOriginal,
|
||||||
|
presentationWithAnnotationsDownloadable: settingsData.presentation.allowDownloadWithAnnotations,
|
||||||
externalVideoPlayer: settingsData.externalVideoPlayer.enabled,
|
externalVideoPlayer: settingsData.externalVideoPlayer.enabled,
|
||||||
presentationHidden: settingsData.layout.hidePresentation,
|
presentationHidden: settingsData.layout.hidePresentation,
|
||||||
// Screensharing
|
// Screensharing
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
"test:filter": "npx playwright test -g",
|
"test:filter": "npx playwright test -g",
|
||||||
"test:headed": "npx playwright test --headed",
|
"test:headed": "npx playwright test --headed",
|
||||||
"test:debug": "npx playwright test --debug -g",
|
"test:debug": "npx playwright test --debug -g",
|
||||||
"test-chromium-ci": "export CI='true' && npx playwright test --project=chromium --grep @ci",
|
"test-chromium-ci": "export CI='true' && npx playwright test --project=chromium --grep @ci --grep-invert @flaky",
|
||||||
"test-firefox-ci": "export CI='true' && npx playwright test --project=firefox --grep @ci",
|
"test-firefox-ci": "export CI='true' && npx playwright test --project=firefox --grep @ci --grep-invert @flaky",
|
||||||
"rewrite-snapshots": "read -p 'CAUTION: You will delete ALL testing folders containing snapshots and run the tests to rewrite these files.\nProceed? (y/n) ' confirm && test $confirm = 'y' && sh core/scripts/rewrite-snapshots.sh"
|
"rewrite-snapshots": "read -p 'CAUTION: You will delete ALL testing folders containing snapshots and run the tests to rewrite these files.\nProceed? (y/n) ' confirm && test $confirm = 'y' && sh core/scripts/rewrite-snapshots.sh"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -4,6 +4,7 @@ const { DisabledFeatures } = require('./disabledFeatures');
|
|||||||
const c = require('./constants');
|
const c = require('./constants');
|
||||||
const { encodeCustomParams, getAllShortcutParams, hexToRgb } = require('./util');
|
const { encodeCustomParams, getAllShortcutParams, hexToRgb } = require('./util');
|
||||||
const { CreateParameters } = require('./createParameters');
|
const { CreateParameters } = require('./createParameters');
|
||||||
|
const { linkIssue } = require('../core/helpers');
|
||||||
|
|
||||||
test.describe.parallel('Create Parameters', () => {
|
test.describe.parallel('Create Parameters', () => {
|
||||||
test('Record Meeting', async ({ browser, context, page }) => {
|
test('Record Meeting', async ({ browser, context, page }) => {
|
||||||
|
@ -122,8 +122,8 @@ class Presentation extends MultiUsers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async enableAndDisablePresentationDownload(testInfo) {
|
async enableAndDisablePresentationDownload(testInfo) {
|
||||||
const { presentationDownloadable } = getSettings();
|
const { originalPresentationDownloadable } = getSettings();
|
||||||
test.fail(!presentationDownloadable, 'Presentation download is disable');
|
test.fail(!originalPresentationDownloadable, 'Presentation download is disable');
|
||||||
|
|
||||||
await this.modPage.waitForSelector(e.whiteboard, ELEMENT_WAIT_LONGER_TIME);
|
await this.modPage.waitForSelector(e.whiteboard, ELEMENT_WAIT_LONGER_TIME);
|
||||||
// enable original presentation download
|
// enable original presentation download
|
||||||
@ -152,8 +152,8 @@ class Presentation extends MultiUsers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async sendPresentationToDownload(testInfo) {
|
async sendPresentationToDownload(testInfo) {
|
||||||
const { presentationDownloadable } = getSettings();
|
const { presentationWithAnnotationsDownloadable } = getSettings();
|
||||||
test.fail(!presentationDownloadable, 'Presentation download is disable');
|
test.fail(!presentationWithAnnotationsDownloadable, 'Presentation download is disable');
|
||||||
|
|
||||||
await this.modPage.waitForSelector(e.whiteboard, ELEMENT_WAIT_LONGER_TIME);
|
await this.modPage.waitForSelector(e.whiteboard, ELEMENT_WAIT_LONGER_TIME);
|
||||||
await this.modPage.waitAndClick(e.actions);
|
await this.modPage.waitAndClick(e.actions);
|
||||||
|
@ -2,9 +2,9 @@ const { test } = require('@playwright/test');
|
|||||||
const { MultiUsers } = require('../user/multiusers');
|
const { MultiUsers } = require('../user/multiusers');
|
||||||
const { Webcam } = require('./webcam');
|
const { Webcam } = require('./webcam');
|
||||||
|
|
||||||
test.describe.parallel('Webcam @ci', () => {
|
test.describe.parallel('Webcam', () => {
|
||||||
// https://docs.bigbluebutton.org/2.6/release-tests.html#joining-webcam-automated
|
// https://docs.bigbluebutton.org/2.6/release-tests.html#joining-webcam-automated
|
||||||
test('Shares webcam', async ({ browser, page }) => {
|
test('Shares webcam @ci', async ({ browser, page }) => {
|
||||||
const webcam = new Webcam(browser, page);
|
const webcam = new Webcam(browser, page);
|
||||||
await webcam.init(true, true);
|
await webcam.init(true, true);
|
||||||
await webcam.share();
|
await webcam.share();
|
||||||
@ -49,7 +49,9 @@ test.describe.parallel('Webcam @ci', () => {
|
|||||||
await webcam.applyBackground();
|
await webcam.applyBackground();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Managing new background', async ({ browser, page }) => {
|
// following test is throwing failures due to mis-comparison screenshot
|
||||||
|
// as the emulated video is not static, we may add a mask in the middle part - where it moves the most
|
||||||
|
test('Managing new background @flaky', async ({ browser, page }) => {
|
||||||
const webcam = new Webcam(browser, page);
|
const webcam = new Webcam(browser, page);
|
||||||
await webcam.init(true, true);
|
await webcam.init(true, true);
|
||||||
await webcam.managingNewBackground();
|
await webcam.managingNewBackground();
|
||||||
|
@ -432,7 +432,8 @@ endWhenNoModeratorDelayInMinutes=1
|
|||||||
# Available options:
|
# Available options:
|
||||||
# chat, sharedNotes, polls, screenshare, externalVideos, presentation, downloadPresentationWithAnnotations
|
# chat, sharedNotes, polls, screenshare, externalVideos, presentation, downloadPresentationWithAnnotations
|
||||||
# learningDashboard, layouts, captions, liveTranscription, virtualBackgrounds, customVirtualBackgrounds
|
# learningDashboard, layouts, captions, liveTranscription, virtualBackgrounds, customVirtualBackgrounds
|
||||||
# breakoutRooms, importSharedNotesFromBreakoutRooms, importPresentationWithAnnotationsFromBreakoutRooms
|
# breakoutRooms, importSharedNotesFromBreakoutRooms, importPresentationWithAnnotationsFromBreakoutRooms,
|
||||||
|
# downloadOriginalPresentation
|
||||||
disabledFeatures=
|
disabledFeatures=
|
||||||
|
|
||||||
# Notify users that recording is on
|
# Notify users that recording is on
|
||||||
|
@ -24,6 +24,15 @@ else
|
|||||||
fi
|
fi
|
||||||
COMMIT_DATE="$(git log -n1 --pretty='format:%cd' --date=format:'%Y%m%dT%H%M%S')"
|
COMMIT_DATE="$(git log -n1 --pretty='format:%cd' --date=format:'%Y%m%dT%H%M%S')"
|
||||||
|
|
||||||
|
# FORCE_GIT_REV and FORCE_COMMIT_DATE are useful for Github Actions be able to cache previous packages
|
||||||
|
# It sets FORCE_GIT_REV=0 and FORCE_COMMIT_DATE=0 in order to keep the same package version always
|
||||||
|
if [ ! -z "$FORCE_GIT_REV" ]; then
|
||||||
|
GIT_REV=$FORCE_GIT_REV
|
||||||
|
fi
|
||||||
|
if [ ! -z "$FORCE_COMMIT_DATE" ]; then
|
||||||
|
COMMIT_DATE=$FORCE_COMMIT_DATE
|
||||||
|
fi
|
||||||
|
|
||||||
# Arrange to write the docker container ID to a temp file, then run
|
# Arrange to write the docker container ID to a temp file, then run
|
||||||
# the container detached and immediately attach it (without stdin) so
|
# the container detached and immediately attach it (without stdin) so
|
||||||
# we can catch CTRL-C in this script and kill the container if so.
|
# we can catch CTRL-C in this script and kill the container if so.
|
||||||
|
@ -118,6 +118,7 @@ For full details on what is new in BigBlueButton 2.7, see the release notes.
|
|||||||
|
|
||||||
Recent releases:
|
Recent releases:
|
||||||
|
|
||||||
|
- [2.7.0-beta.3](https://github.com/bigbluebutton/bigbluebutton/releases/tag/v2.7.0-beta.3)
|
||||||
- [2.7.0-beta.2](https://github.com/bigbluebutton/bigbluebutton/releases/tag/v2.7.0-beta.2)
|
- [2.7.0-beta.2](https://github.com/bigbluebutton/bigbluebutton/releases/tag/v2.7.0-beta.2)
|
||||||
- [2.7.0-beta.1](https://github.com/bigbluebutton/bigbluebutton/releases/tag/v2.7.0-beta.1)
|
- [2.7.0-beta.1](https://github.com/bigbluebutton/bigbluebutton/releases/tag/v2.7.0-beta.1)
|
||||||
- [2.7.0-alpha.3](https://github.com/bigbluebutton/bigbluebutton/releases/tag/v2.7.0-alpha.3)
|
- [2.7.0-alpha.3](https://github.com/bigbluebutton/bigbluebutton/releases/tag/v2.7.0-alpha.3)
|
||||||
@ -130,6 +131,10 @@ Recent releases:
|
|||||||
|
|
||||||
If you are using bbb-install to configure your servers, be aware that starting with BigBlueButton 2.6's version of bbb-install by default we install a local TURN server. For more information: https://github.com/bigbluebutton/bbb-install/pull/579 and https://docs.bigbluebutton.org/administration/turn-server
|
If you are using bbb-install to configure your servers, be aware that starting with BigBlueButton 2.6's version of bbb-install by default we install a local TURN server. For more information: https://github.com/bigbluebutton/bbb-install/pull/579 and https://docs.bigbluebutton.org/administration/turn-server
|
||||||
|
|
||||||
|
#### Changing the default setting `guestPolicyExtraAllowOptions`
|
||||||
|
|
||||||
|
Starting with BigBlueButton 2.7.0-beta.3 we are hiding by default a couple extra options in the guest approve panel. 'Allow all authenticated users' and 'Allow all guests' options will be hidden unless you override the option `app.public.guestPolicyExtraAllowOptions` in `bbb-html5` config file `settings.yml`. These extra options were not relevant to the vast majority of the use cases and when hidden, the interface becomes much simpler.
|
||||||
|
|
||||||
### Development
|
### Development
|
||||||
|
|
||||||
For information on developing in BigBlueButton, see [setting up a development environment for 2.7](/development/guide).
|
For information on developing in BigBlueButton, see [setting up a development environment for 2.7](/development/guide).
|
||||||
|
Loading…
Reference in New Issue
Block a user