diff --git a/.github/workflows/build-and-deploy.yml b/.github/workflows/build-and-deploy.yml
index ebb2b90e..59a002db 100644
--- a/.github/workflows/build-and-deploy.yml
+++ b/.github/workflows/build-and-deploy.yml
@@ -27,17 +27,6 @@ jobs:
run: |
mkdir $HOME/.kube
echo "${{ secrets.KUBE_CONFIG_DATA }}" > $HOME/.kube/config
-
- - name: Run Unit Test
- run: |
- cd react
- npm install --include=dev
- npm test
-
- - name: Upload coverage to Codecov
- uses: codecov/codecov-action@v4
- with:
- token: ${{ secrets.CODECOV_TOKEN }}
- name: Set up JDK 17
uses: actions/setup-java@v3
@@ -113,7 +102,7 @@ jobs:
cp target/*.war /tmp/circle-webinar.war
cd ..
- - name: Build React application
+ - name: Build React application for conferencing
env:
CI: false
NODE_OPTIONS: '--max-old-space-size=4096'
@@ -129,7 +118,7 @@ jobs:
rm -r webapp/src/main/webapp/static/*
cp -a react/build/. webapp/src/main/webapp
- - name: Build Maven project
+ - name: Build Maven project for conferencing
run: |
cd webapp
mvn clean install -DskipTests -Dgpg.skip=true --quiet
@@ -137,92 +126,261 @@ jobs:
ls -alh target/
cp target/*.war /tmp/circle-conferencing.war
cd ..
-
- - name: Install Test Tool
+
+ - name: Create Test Tool
run: |
sudo apt-get update
sudo apt-get install -y unzip iproute2 libva-drm2 libva-x11-2 libvdpau-dev ffmpeg
git clone https://gitlab.com/Ant-Media/webrtc-test.git
cd webrtc-test
./redeploy.sh
- cp target/webrtc-load-test-tool-*.zip ../
cd ..
- unzip webrtc-load-test-tool-*.zip
- mkdir ~/test
- mv webrtc-load-test ~/test
-
- - name: Install Selenium
- run: |
- wget https://storage.googleapis.com/chrome-for-testing-public/130.0.6723.58/linux64/chromedriver-linux64.zip
- unzip chromedriver-linux64.zip
- sudo cp chromedriver-linux64/chromedriver /tmp
- ls -al /tmp
- pip3 install selenium==4.14
- pip3 install requests
- pip3 show selenium
- pip3 install psutil
-
- - name: Run Integration Test
- run: |
- cd test
- python3 test_main.py ${{ secrets.STAGING_SERVER_URL }} ${{ secrets.USER_NAME }} ${{ secrets.PASSWORD }} /tmp/circle-conferencing.war false
- - name: Run Integration Test for webinar
- run: |
- cd test
- python3 test_main.py ${{ secrets.STAGING_SERVER_URL }} ${{ secrets.USER_NAME }} ${{ secrets.PASSWORD }} /tmp/circle-webinar.war true
+ - name: Cache Test Tool
+ uses: actions/cache@v3
+ with:
+ path: webrtc-test/
+ key: test-tool-${{ hashFiles('**/tool-source/**') }}
+ restore-keys: test-tool-
- - name: Copy Logs From Pods
- if: always()
- run: |
- for pod in $(kubectl -n circle get pods | grep "ant-media-server" | awk '{print $1}'); do
- node_ip=$(kubectl -n circle get pods -o wide | grep "$pod" | awk '{print $6}')
- kubectl -n circle cp $pod:/usr/local/antmedia/log/ant-media-server.log /tmp/ant-media-server-$node_ip.log
- kubectl -n circle cp $pod:/usr/local/antmedia/log/antmedia-error.log /tmp/antmedia-error-$node_ip.log
- done
- - name: Upload PNG files as artifacts
+ - name: Upload conferencing war file as artifact
if: always()
uses: actions/upload-artifact@v4
with:
- name: screenshots
- path: ${{ github.workspace }}/test/**/*.png
+ name: circle-conferencing.war
+ path: /tmp/circle-conferencing.war
- - name: Upload log files as artifacts
+ - name: Upload webinar war file as artifact
if: always()
uses: actions/upload-artifact@v4
with:
- name: logs
- path: /tmp/*.log
+ name: circle-webinar.war
+ path: /tmp/circle-webinar.war
+
+ - name: Debug WAR file paths
+ run: ls -alh /tmp
- - name: Upload war files as artifacts
- if: always()
- uses: actions/upload-artifact@v4
+ unit-tests:
+ needs: [build]
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v3
+
+ - name: Run Unit Test
+ run: |
+ echo "pwd:"
+ pwd
+ echo "ls:"
+ ls -al
+ cd react
+ npm install --include=dev
+ npm test
+
+ - name: Upload coverage to Codecov
+ uses: codecov/codecov-action@v4
+ with:
+ token: ${{ secrets.CODECOV_TOKEN }}
+
+ conference-integration-tests:
+ needs: [build]
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v3
+
+ - name: Restore Cached Test Tool
+ uses: actions/cache@v3
+ with:
+ path: webrtc-test/
+ key: test-tool-${{ hashFiles('**/tool-source/**') }}
+ restore-keys: test-tool-
+
+ - name: Locate Test Tool
+ run: |
+ pwd
+ ls
+ cp webrtc-test/target/webrtc-load-test-tool-*.zip ../
+ cd ..
+ unzip webrtc-load-test-tool-*.zip
+ mkdir ~/test
+ mv webrtc-load-test ~/test
+ ls -al ~/test
+
+ - name: Set up JDK 17
+ uses: actions/setup-java@v3
+ with:
+ java-version: 17
+ distribution: 'temurin'
+ server-id: ossrh # Value of the distributionManagement/repository/id field of the pom.xml
+ server-username: MAVEN_USERNAME # env variable for username in deploy
+ server-password: MAVEN_PASSWORD # env variable for token in deploy
+ gpg-private-key: ${{ secrets.MVN_GPG_KEY }} # Value of the GPG private key to import
+ gpg-passphrase: MAVEN_GPG_PASSPHRASE # env variable for GPG private key passphrase
+
+ - name: Download circle-conferencing.war Artifact
+ uses: actions/download-artifact@v4
+ with:
+ name: circle-conferencing.war
+ path: /tmp
+
+ - name: Debug WAR file paths
+ run: ls -alh /tmp
+
+ - name: Install Selenium
+ run: |
+ wget https://storage.googleapis.com/chrome-for-testing-public/130.0.6723.58/linux64/chromedriver-linux64.zip
+ unzip chromedriver-linux64.zip
+ sudo cp chromedriver-linux64/chromedriver /tmp
+ ls -al /tmp
+ pip3 install selenium==4.14
+ pip3 install requests
+ pip3 show selenium
+ pip3 install psutil
+
+ - name: Run Integration Test
+ run: |
+ cd test
+ python3 test_main.py ${{ secrets.STAGING_SERVER_URL }} ${{ secrets.USER_NAME }} ${{ secrets.PASSWORD }} /tmp/circle-conferencing.war false
+
+ - name: Upload PNG files as artifacts
+ if: always()
+ uses: actions/upload-artifact@v4
+ with:
+ name: screenshots
+ path: ${{ github.workspace }}/test/**/*.png
+
+ webinar-integration-tests:
+ needs: [build]
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v3
+
+ - name: Restore Cached Test Tool
+ uses: actions/cache@v3
+ with:
+ path: webrtc-test/
+ key: test-tool-${{ hashFiles('**/tool-source/**') }}
+ restore-keys: test-tool-
+
+ - name: Locate Test Tool
+ run: |
+ pwd
+ ls
+ cp webrtc-test/target/webrtc-load-test-tool-*.zip ../
+ cd ..
+ unzip webrtc-load-test-tool-*.zip
+ mkdir ~/test
+ mv webrtc-load-test ~/test
+
+ - name: Download circle-webinar.war Artifact
+ uses: actions/download-artifact@v4
+ with:
+ name: circle-webinar.war
+ path: /tmp
+
+ - name: Debug WAR file paths
+ run: ls -alh /tmp
+
+ - name: Install Selenium
+ run: |
+ wget https://storage.googleapis.com/chrome-for-testing-public/130.0.6723.58/linux64/chromedriver-linux64.zip
+ unzip chromedriver-linux64.zip
+ sudo cp chromedriver-linux64/chromedriver /tmp
+ ls -al /tmp
+ pip3 install selenium==4.14
+ pip3 install requests
+ pip3 show selenium
+ pip3 install psutil
+
+ - name: Run Integration Test for webinar
+ run: |
+ sleep 10
+ cd test
+ python3 test_main.py ${{ secrets.STAGING_SERVER_URL }} ${{ secrets.USER_NAME }} ${{ secrets.PASSWORD }} /tmp/circle-webinar.war true
+
+
+ collect-and-upload-logs:
+ needs: [unit-tests, webinar-integration-tests , conference-integration-tests]
+ if: always()
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Upload PNG files as artifacts
+ if: always()
+ uses: actions/upload-artifact@v4
+ with:
+ name: screenshots
+ path: ${{ github.workspace }}/test/**/*.png
+
+ - name: Copy Logs From Pods
+ if: always()
+ run: |
+ for pod in $(kubectl -n circle get pods | grep "ant-media-server" | awk '{print $1}'); do
+ node_ip=$(kubectl -n circle get pods -o wide | grep "$pod" | awk '{print $6}')
+ kubectl -n circle cp $pod:/usr/local/antmedia/log/ant-media-server.log /tmp/ant-media-server-$node_ip.log
+ kubectl -n circle cp $pod:/usr/local/antmedia/log/antmedia-error.log /tmp/antmedia-error-$node_ip.log
+ done
+
+ - name: Upload log files as artifacts
+ if: always()
+ uses: actions/upload-artifact@v4
+ with:
+ name: logs
+ path: /tmp/*.log
+
+
+ deploy:
+ runs-on: ubuntu-latest
+ needs: collect-and-upload-logs
+ if: github.ref == 'refs/heads/main'
+
+ steps:
+ - uses: actions/checkout@v3
+
+ - name: Set up JDK 17
+ uses: actions/setup-java@v3
with:
- name: wars
- path: /tmp/*.war
-
+ java-version: 17
+ distribution: 'temurin'
+ server-id: ossrh # Value of the distributionManagement/repository/id field of the pom.xml
+ server-username: MAVEN_USERNAME # env variable for username in deploy
+ server-password: MAVEN_PASSWORD # env variable for token in deploy
+ gpg-private-key: ${{ secrets.MVN_GPG_KEY }} # Value of the GPG private key to import
+ gpg-passphrase: MAVEN_GPG_PASSPHRASE # env variable for GPG private key passphrase
+
+ - name: Build React application for conferencing
+ env:
+ CI: false
+ NODE_OPTIONS: '--max-old-space-size=4096'
+ run: |
+ cd react
+ mv .env.production.conferencing .env.production
+ sed -i "s#^REACT_APP_TURN_SERVER_URL=.*#REACT_APP_TURN_SERVER_URL=\"turn:${{ secrets.STAGING_TURN_URL }}\"#" .env.production
+ sed -i "s#^REACT_APP_TURN_SERVER_USERNAME=.*#REACT_APP_TURN_SERVER_USERNAME=\"${{ secrets.STAGING_TURN_USERNAME }}\"#" .env.production
+ sed -i "s#^REACT_APP_TURN_SERVER_CREDENTIAL=.*#REACT_APP_TURN_SERVER_CREDENTIAL=\"${{ secrets.STAGING_TURN_PASSWORD }}\"#" .env.production
+ npm install
+ npm run build
+ cd ..
+ rm -r webapp/src/main/webapp/static/*
+ cp -a react/build/. webapp/src/main/webapp
+
- name: Publish to Maven Central
- if: github.ref == 'refs/heads/main'
run: |
cd webapp
ls -alh
ls -alh target/
mvn -e deploy -DskipTests --quiet --settings ../mvn-settings.xml
+ sleep 60
env:
MAVEN_USERNAME: ${{ secrets.MVN_USERNAME }}
MAVEN_PASSWORD: ${{ secrets.MVN_PASSWORD }}
MAVEN_GPG_PASSPHRASE: ${{ secrets.MVN_GPG_PASSPHRASE }}
-
- deploy:
- runs-on: ubuntu-latest
- needs: build
- if: github.ref == 'refs/heads/main'
-
- steps:
- - uses: actions/checkout@v3
-
- name: Get versions data from repo
run: wget -O maven-metadata.xml https://oss.sonatype.org/service/local/repositories/snapshots/content/io/antmedia/ant-media-server/maven-metadata.xml
- name: Install jq
diff --git a/react/.env.production b/react/.env.production
index 1c31d149..983d5469 100644
--- a/react/.env.production
+++ b/react/.env.production
@@ -55,6 +55,7 @@ REACT_APP_TIME_ZONE_LIVE_TEXT_VISIBILITY=true
# Video Overlay configurations
REACT_APP_VIDEO_OVERLAY_ADMIN_MODE_ENABLED=false
+REACT_APP_VIDEO_OVERLAY_ADMIN_CAMERA_CONTROL_ENABLED=false
# Participant Tab configurations
REACT_APP_PARTICIPANT_TAB_ADMIN_MODE_ENABLED=true
diff --git a/react/.env.production.webinar b/react/.env.production.webinar
index 4bf483ea..41eaf94e 100644
--- a/react/.env.production.webinar
+++ b/react/.env.production.webinar
@@ -55,6 +55,7 @@ REACT_APP_TIME_ZONE_LIVE_TEXT_VISIBILITY=true
# Video Overlay configurations
REACT_APP_VIDEO_OVERLAY_ADMIN_MODE_ENABLED=true
+REACT_APP_VIDEO_OVERLAY_ADMIN_CAMERA_CONTROL_ENABLED=false
# Speed Test configurations
REACT_APP_SPEED_TEST_BEFORE_JOINING_THE_ROOM=true
diff --git a/react/src/Components/Cards/VideoCard.js b/react/src/Components/Cards/VideoCard.js
index bcd174d8..074ff7f8 100644
--- a/react/src/Components/Cards/VideoCard.js
+++ b/react/src/Components/Cards/VideoCard.js
@@ -113,7 +113,7 @@ function VideoCard(props) {
return (
<>
- {!useAvatar && (
+ {(!useAvatar && process.env.REACT_APP_VIDEO_OVERLAY_ADMIN_MODE_ENABLED === "true") && (
>
diff --git a/react/src/Components/ParticipantTab.js b/react/src/Components/ParticipantTab.js
index 71d73269..4ac7fcc9 100644
--- a/react/src/Components/ParticipantTab.js
+++ b/react/src/Components/ParticipantTab.js
@@ -63,7 +63,7 @@ function ParticipantTab(props) {
onClick={() => { handleToggleMic(micMuted, streamId, name) }
}
>
-
+
)
}
diff --git a/react/src/__tests__/pages/AntMedia.test.js b/react/src/__tests__/pages/AntMedia.test.js
index 42382280..03d61009 100644
--- a/react/src/__tests__/pages/AntMedia.test.js
+++ b/react/src/__tests__/pages/AntMedia.test.js
@@ -87,6 +87,7 @@ jest.mock('@antmedia/webrtc_adaptor', () => ({
enableEffect: jest.fn(),
setSelectedVideoEffect: jest.fn(),
setBlurEffectRange: jest.fn(),
+ getSubtrackCount: jest.fn(),
}
for (var key in params) {
diff --git a/react/src/pages/AntMedia.js b/react/src/pages/AntMedia.js
index 68caf7f7..5dd9d4ef 100644
--- a/react/src/pages/AntMedia.js
+++ b/react/src/pages/AntMedia.js
@@ -1575,6 +1575,7 @@ function AntMedia(props) {
setIsPlayed(true);
setIsNoSreamExist(false);
webRTCAdaptor?.getBroadcastObject(roomName);
+ webRTCAdaptor?.getSubtrackCount(roomName, null, null);
webRTCAdaptor?.getSubtracks(roomName, null, globals.participantListPagination.offset, globals.participantListPagination.pageSize);
requestVideoTrackAssignmentsInterval();
@@ -2276,6 +2277,8 @@ function AntMedia(props) {
let tempVideoTrackAssignmentsNew = [];
+ let tempAllParticipants = {...allParticipants};
+
// This function checks the case 1 and case 2
currentVideoTrackAssignments.forEach(tempVideoTrackAssignment => {
let assignment;
@@ -2295,12 +2298,13 @@ function AntMedia(props) {
} else {
console.log("---> Removed video track assignment: " + tempVideoTrackAssignment.videoLabel);
+ delete tempAllParticipants[tempVideoTrackAssignment.streamId];
}
});
- currentVideoTrackAssignments = [...tempVideoTrackAssignmentsNew];
+ setAllParticipants(tempAllParticipants);
- //let updateAllParticipants = {...allParticipants};
+ currentVideoTrackAssignments = [...tempVideoTrackAssignmentsNew];
// update participants according to current assignments
receivedVideoTrackAssignments.forEach(vta => {
@@ -2310,23 +2314,9 @@ function AntMedia(props) {
existingAssignment.isReserved = vta.reserved;
}
if (!allParticipants[vta.trackId]) {
- /*
- updateAllParticipants[vta.trackId] = {
- streamId: vta.trackId,
- name: vta.trackId,
- isScreenShared: false,
- isPinned: false,
- isFake: false,
- isMine: false,
- status: "livestream"
- metaData: "{\"isMicMuted\":true,\"isCameraOn\":false,\"isScreenShared\":false,\"playOnly\":false}"
- };
- */
webRTCAdaptor?.getBroadcastObject(vta.trackId);
}
});
-
- //setAllParticipants(updateAllParticipants);
checkScreenSharingStatus();
diff --git a/react/src/styles/sprite.svg b/react/src/styles/sprite.svg
index a0f984ea..ab5b7cb4 100644
--- a/react/src/styles/sprite.svg
+++ b/react/src/styles/sprite.svg
@@ -23,7 +23,7 @@
-
+
@@ -112,7 +112,7 @@
-
+
diff --git a/test/test_join_leave.py b/test/test_join_leave.py
index b31241d5..61a035e4 100644
--- a/test/test_join_leave.py
+++ b/test/test_join_leave.py
@@ -48,8 +48,8 @@ def create_participants_with_test_tool(self, participant_name, room, count):
process = subprocess.Popen(
["bash", script_path] + parameters,
cwd=directory,
- stdout=subprocess.DEVNULL,
- stderr=subprocess.DEVNULL
+ #stdout=subprocess.DEVNULL,
+ #stderr=subprocess.DEVNULL
)
return process
diff --git a/test/test_main.py b/test/test_main.py
index 29be86d4..96a295eb 100644
--- a/test/test_main.py
+++ b/test/test_main.py
@@ -1,6 +1,8 @@
import test_join_leave
import test_webinar
from test_deployment import TestDeployment
+from test_join_leave import TestJoinLeave
+
import unittest
import sys
@@ -12,21 +14,26 @@
os.environ['AMS_PASSWORD'] = sys.argv[3]
os.environ['WAR_FILE'] = sys.argv[4]
use_test_webinar = sys.argv[5].lower() == 'true'
-os.environ['TEST_APP_NAME'] = "TestAPP"+str(random.randint(100, 999))
+app_name_prefix = "webinar" if use_test_webinar else "conference"
+os.environ['TEST_APP_NAME'] = app_name_prefix + str(random.randint(100, 999))
+
+#Keep it True to stop tests immediately after a failed test
+fail_fast = True
suite = unittest.TestSuite()
suite.addTest(TestDeployment('test_install_app'))
suite2 = None
-
if use_test_webinar:
suite2 = unittest.TestLoader().loadTestsFromModule(test_webinar)
else:
suite2 = unittest.TestLoader().loadTestsFromModule(test_join_leave)
suite.addTests(suite2)
-suite.addTest(TestDeployment('test_delete_app'))
-ret = not unittest.TextTestRunner(verbosity=2, failfast=True).run(suite).wasSuccessful()
-sys.exit(ret)
+#suite.addTest(TestJoinLeave("test_join_without_camera_mic"))
+
+suite.addTest(TestDeployment('test_delete_app'))
+ret = not unittest.TextTestRunner(verbosity=2, failfast=fail_fast).run(suite).wasSuccessful()
+sys.exit(ret)
\ No newline at end of file
diff --git a/test/test_webinar.py b/test/test_webinar.py
index 7e350ab5..def55405 100644
--- a/test/test_webinar.py
+++ b/test/test_webinar.py
@@ -143,6 +143,8 @@ def join_room_as_player(self, participant, room):
app = ""
handle = self.chrome.open_in_new_tab(self.url+app+"/"+room+"?playOnly=true&role=listener&streamName="+participant)
+ wait = self.chrome.get_wait()
+
#name_text_box = self.chrome.get_element_with_retry(By.ID,"participant_name")
#self.chrome.write_to_element(name_text_box, participant)
@@ -155,7 +157,7 @@ def join_room_as_player(self, participant, room):
time.sleep(5)
speedTestCircularProgress = self.chrome.get_element_with_retry(By.ID,"speed-test-modal-circle-progress-bar", retries=20)
- assert(speedTestCircularProgress.is_displayed())
+ wait.until(lambda x: speedTestCircularProgress.is_displayed())
time.sleep(5)