Skip to content
This repository was archived by the owner on Apr 2, 2026. It is now read-only.

chore(deps): bump lodash.unset from 4.5.2 to 4.18.0 in /desktop/electron #5

chore(deps): bump lodash.unset from 4.5.2 to 4.18.0 in /desktop/electron

chore(deps): bump lodash.unset from 4.5.2 to 4.18.0 in /desktop/electron #5

name: Build, push, test and deploy Docker image
on:
push:
branches: [master, develop]
release:
types: [created]
pull_request:
types: [labeled, synchronize, opened, reopened]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build-play:
uses: ./.github/workflows/build-multi-arch-image.yml
secrets: inherit
with:
ghcr-dev-build-image-name: 'ghcr.io/workadventure/play-dev-build'
ghcr-image-name: 'ghcr.io/workadventure/play'
dockerio-image-name: 'thecodingmachine/workadventure-play'
# FIXME: Final build should only build on master or tags
final_build: ${{ github.event_name == 'push' || github.event_name == 'release' || (github.event_name == 'pull_request' && (contains(github.event.pull_request.labels.*.name, 'deploy') || contains(github.event.pull_request.labels.*.name, 'build') || contains(github.event.pull_request.labels.*.name, 'linked_to_saas_branch'))) }}
dockerfile: play/Dockerfile
short_name: play
# sentry_project: play
# We only push to the registry if we are in the WorkAdventure organization. Otherwise, we will use artifacts because GITHUB_TOKEN from a public fork have no write access, even to the local user repository.
push-to-registry: ${{ (github.event_name == 'pull_request' && github.event.pull_request.head.repo.owner.login == 'workadventure') || (github.event_name != 'pull_request' && github.repository_owner == 'workadventure') }}
context: ./
build-back:
uses: ./.github/workflows/build-multi-arch-image.yml
secrets: inherit
with:
ghcr-dev-build-image-name: 'ghcr.io/workadventure/back-dev-build'
ghcr-image-name: 'ghcr.io/workadventure/back'
dockerio-image-name: 'thecodingmachine/workadventure-back'
final_build: ${{ github.event_name == 'push' || github.event_name == 'release' || github.event_name == 'pull_request' && (contains(github.event.pull_request.labels.*.name, 'deploy') || contains(github.event.pull_request.labels.*.name, 'build') || contains(github.event.pull_request.labels.*.name, 'linked_to_saas_branch')) }}
dockerfile: back/Dockerfile
short_name: back
sentry_project: back
# We only push to the registry if we are in the WorkAdventure organization. Otherwise, we will use artifacts because GITHUB_TOKEN from a public fork have no write access, even to the local user repository.
push-to-registry: ${{ (github.event_name == 'pull_request' && github.event.pull_request.head.repo.owner.login == 'workadventure') || (github.event_name != 'pull_request' && github.repository_owner == 'workadventure') }}
context: ./
build-uploader:
uses: ./.github/workflows/build-multi-arch-image.yml
secrets: inherit
with:
ghcr-dev-build-image-name: 'ghcr.io/workadventure/uploader-dev-build'
ghcr-image-name: 'ghcr.io/workadventure/uploader'
dockerio-image-name: 'thecodingmachine/workadventure-uploader'
final_build: ${{ github.event_name == 'push' || github.event_name == 'release' || github.event_name == 'pull_request' && (contains(github.event.pull_request.labels.*.name, 'deploy') || contains(github.event.pull_request.labels.*.name, 'build') || contains(github.event.pull_request.labels.*.name, 'linked_to_saas_branch')) }}
dockerfile: uploader/Dockerfile
short_name: uploader
sentry_project: uploader
# We only push to the registry if we are in the WorkAdventure organization. Otherwise, we will use artifacts because GITHUB_TOKEN from a public fork have no write access, even to the local user repository.
push-to-registry: ${{ (github.event_name == 'pull_request' && github.event.pull_request.head.repo.owner.login == 'workadventure') || (github.event_name != 'pull_request' && github.repository_owner == 'workadventure') }}
context: ./
build-maps:
uses: ./.github/workflows/build-multi-arch-image.yml
secrets: inherit
with:
ghcr-dev-build-image-name: 'ghcr.io/workadventure/maps-dev-build'
ghcr-image-name: 'ghcr.io/workadventure/maps'
dockerio-image-name: 'thecodingmachine/workadventure-maps'
final_build: ${{ github.event_name == 'push' || github.event_name == 'release' || github.event_name == 'pull_request' && (contains(github.event.pull_request.labels.*.name, 'deploy') || contains(github.event.pull_request.labels.*.name, 'build') || contains(github.event.pull_request.labels.*.name, 'linked_to_saas_branch')) }}
dockerfile: maps/Dockerfile
short_name: maps
sentry_project: maps
# We only push to the registry if we are in the WorkAdventure organization. Otherwise, we will use artifacts because GITHUB_TOKEN from a public fork have no write access, even to the local user repository.
push-to-registry: ${{ (github.event_name == 'pull_request' && github.event.pull_request.head.repo.owner.login == 'workadventure') || (github.event_name != 'pull_request' && github.repository_owner == 'workadventure') }}
context: ./maps
build-map-storage:
uses: ./.github/workflows/build-multi-arch-image.yml
secrets: inherit
with:
ghcr-dev-build-image-name: 'ghcr.io/workadventure/map-storage-dev-build'
ghcr-image-name: 'ghcr.io/workadventure/map-storage'
dockerio-image-name: 'thecodingmachine/workadventure-map-storage'
final_build: ${{ github.event_name == 'push' || github.event_name == 'release' || github.event_name == 'pull_request' && (contains(github.event.pull_request.labels.*.name, 'deploy') || contains(github.event.pull_request.labels.*.name, 'build') || contains(github.event.pull_request.labels.*.name, 'linked_to_saas_branch')) }}
dockerfile: map-storage/Dockerfile
short_name: map-storage
sentry_project: map-storage
# We only push to the registry if we are in the WorkAdventure organization. Otherwise, we will use artifacts because GITHUB_TOKEN from a public fork have no write access, even to the local user repository.
push-to-registry: ${{ (github.event_name == 'pull_request' && github.event.pull_request.head.repo.owner.login == 'workadventure') || (github.event_name != 'pull_request' && github.repository_owner == 'workadventure') }}
context: ./
push-to-sentry:
runs-on: ubuntu-latest
#if: ${{ github.event_name == 'push' || github.event_name == 'release' || github.event_name == 'pull_request' && (contains(github.event.pull_request.labels.*.name, 'deploy') || contains(github.event.pull_request.labels.*.name, 'build')) }}
if: ${{ github.event_name == 'release' || (github.event_name == 'push' && github.ref == 'refs/heads/master') }}
needs:
# - build-play
- build-back
- build-map-storage
steps:
# - name: Sentry push play source maps
# continue-on-error: true
# env:
# SENTRY_URL: ${{ secrets.SENTRY_URL }}
# SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
# SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
# SENTRY_PROJECT: pusher
# SENTRY_ENVIRONMENT: ${{ github.event_name == 'release' && 'production' || env.GITHUB_REF_NAME == 'master' && 'staging' || null }}
# SENTRY_RELEASE: ${{ github.event_name == 'release' && env.GITHUB_REF_NAME || format('{0}@{1}', env.GITHUB_REF_NAME, env.GITHUB_SHA) }}
# run: |
# docker run --rm \
# --user 0 \
# -e SENTRY_URL \
# -e SENTRY_AUTH_TOKEN \
# -e SENTRY_ORG \
# -e SENTRY_PROJECT \
# -e SENTRY_RELEASE \
# -e SENTRY_ENVIRONMENT \
# ghcr.io/workadventure/play-dev-build:amd64-${{ github.sha }} \
# /bin/sh -c 'npm install --dev && npm run push-sentry-sourcemaps'
- name: Sentry push back source maps
env:
SENTRY_URL: ${{ secrets.SENTRY_URL }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
SENTRY_PROJECT: back
SENTRY_ENVIRONMENT: ${{ github.event_name == 'release' && 'production' || env.GITHUB_REF_NAME == 'master' && 'staging' || null }}
SENTRY_RELEASE: ${{ github.event_name == 'release' && env.GITHUB_REF_NAME || format('{0}@{1}', env.GITHUB_REF_NAME, env.GITHUB_SHA) }}
run: |
docker run --rm \
--user 0 \
-e SENTRY_URL \
-e SENTRY_AUTH_TOKEN \
-e SENTRY_ORG \
-e SENTRY_PROJECT \
-e SENTRY_RELEASE \
-e SENTRY_ENVIRONMENT \
ghcr.io/workadventure/back-dev-build:amd64-${{ github.sha }} \
/bin/sh -c 'npm install --dev && npm run push-sentry-sourcemaps'
- name: Sentry push map-storage source maps
env:
SENTRY_URL: ${{ secrets.SENTRY_URL }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
SENTRY_PROJECT: map-storage
SENTRY_ENVIRONMENT: ${{ github.event_name == 'release' && 'production' || env.GITHUB_REF_NAME == 'master' && 'staging' || null }}
SENTRY_RELEASE: ${{ github.event_name == 'release' && env.GITHUB_REF_NAME || format('{0}@{1}', env.GITHUB_REF_NAME, env.GITHUB_SHA) }}
run: |
docker run --rm \
--user 0 \
-e SENTRY_URL \
-e SENTRY_AUTH_TOKEN \
-e SENTRY_ORG \
-e SENTRY_PROJECT \
-e SENTRY_RELEASE \
-e SENTRY_ENVIRONMENT \
ghcr.io/workadventure/map-storage-dev-build:amd64-${{ github.sha }} \
/bin/sh -c 'cd /usr/src && npm ci -w map-storage && cd /usr/src/map-storage && npm run push-sentry-sourcemaps'
end-to-end-tests:
name: "End to end tests with ${{ matrix.project }} ${{ matrix.shard }}/${{ matrix.nbShards }}"
strategy:
fail-fast: false
matrix:
include:
- browser: chromium
parameters: --project=chromium
project: chromium
shard: 1
nbShards: 4
renderer: auto
ignoreTags: "@nodesktop"
- browser: chromium
parameters: --project=chromium
project: chromium
shard: 2
nbShards: 4
renderer: auto
ignoreTags: "@nodesktop"
- browser: chromium
parameters: --project=chromium
project: chromium
shard: 3
nbShards: 4
renderer: auto
ignoreTags: "@nodesktop"
- browser: chromium
parameters: --project=chromium
project: chromium
shard: 4
nbShards: 4
renderer: auto
ignoreTags: "@nodesktop"
- browser: firefox
parameters: --project=firefox
project: firefox
shard: 1
nbShards: 4
renderer: auto
ignoreTags: "@nofirefox|@nodesktop"
- browser: firefox
parameters: --project=firefox
project: firefox
shard: 2
nbShards: 4
renderer: auto
ignoreTags: "@nofirefox|@nodesktop"
- browser: firefox
parameters: --project=firefox
project: firefox
shard: 3
nbShards: 4
renderer: auto
ignoreTags: "@nofirefox|@nodesktop"
- browser: firefox
parameters: --project=firefox
project: firefox
shard: 4
nbShards: 4
renderer: auto
ignoreTags: "@nofirefox|@nodesktop"
- browser: webkit
parameters: --project=webkit
project: webkit
shard: 1
nbShards: 3
renderer: headless
ignoreTags: "@nowebkit|@nodesktop"
- browser: webkit
parameters: --project=webkit
project: webkit
shard: 2
nbShards: 3
renderer: headless
ignoreTags: "@nowebkit|@nodesktop"
- browser: webkit
parameters: --project=webkit
project: webkit
shard: 3
nbShards: 3
renderer: headless
ignoreTags: "@nowebkit|@nodesktop"
- browser: ""
parameters: --project=mobilechromium
project: mobilechromium
shard: 1
nbShards: 1
renderer: auto
ignoreTags: "@nomobile"
- browser: ""
parameters: --project=mobilefirefox
project: mobilefirefox
shard: 1
nbShards: 1
renderer: auto
ignoreTags: "@nomobile|@nofirefox"
- browser: ""
parameters: --project=mobilewebkit
project: mobilewebkit
shard: 1
nbShards: 1
renderer: headless
ignoreTags: "@nomobile|@nowebkit"
needs:
- build-play
- build-back
- build-maps
- build-uploader
- build-map-storage
timeout-minutes: 60
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v3
with:
node-version: 22
- name: Install dependencies
run: npm ci
working-directory: tests
- name: Install Playwright
run: npx playwright install --with-deps ${{ matrix.browser }}
working-directory: tests
- name: 'Setup .env file'
run: cp .env.template .env
- uses: rlespinasse/github-slug-action@4.2.3
- name: Display pulled version
run: echo "Pulling images with tag ${DOCKER_TAG}"
env:
DOCKER_TAG: ${{ github.event_name == 'pull_request' && env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }}
- name: "Install Room Api client dependencies"
run: npm ci
working-directory: "libs/room-api-clients/room-api-client-js"
- name: "Build Room Api client proto files"
run: npm run ts-proto
working-directory: "libs/room-api-clients/room-api-client-js"
- name: Fill .env file
run: |
sed -i "s/ROOM_API_SECRET_KEY=/ROOM_API_SECRET_KEY=MYAWESOMEKEY/g" .env
sed -i "s/KLAXOON_ENABLED=false/KLAXOON_ENABLED=true/g" .env
sed -i "s/KLAXOON_CLIENT_ID=/KLAXOON_CLIENT_ID=${{ env.KLAXOON_CLIENT_ID }}/g" .env
sed -i "s/MAP_STORAGE_API_TOKEN=/MAP_STORAGE_API_TOKEN=MYAWESOMEKEY/g" .env
sed -i "s/OPENID_PROMPT=/OPENID_PROMPT=login/g" .env
sed -i "s/MAX_USERS_FOR_WEBRTC=4/MAX_USERS_FOR_WEBRTC=3/g" .env
sed -i "s/LIVEKIT_HOST=/LIVEKIT_HOST=http:\/\/livekit.workadventure.localhost/g" .env
sed -i "s/LIVEKIT_API_KEY=/LIVEKIT_API_KEY=devkey/g" .env
sed -i "s/LIVEKIT_API_SECRET=/LIVEKIT_API_SECRET=12345678901234567890123456789012/g" .env
env:
KLAXOON_CLIENT_ID: ${{ secrets.KLAXOON_CLIENT_ID }}
- name: Download artifact
if: ${{ (github.event_name != 'pull_request' || github.event.pull_request.head.repo.owner.login != 'workadventure') && (github.event_name == 'pull_request' || github.repository_owner != 'workadventure') }}
uses: actions/download-artifact@v4
with:
name: play
path: /tmp
- name: Download artifact
if: ${{ (github.event_name != 'pull_request' || github.event.pull_request.head.repo.owner.login != 'workadventure') && (github.event_name == 'pull_request' || github.repository_owner != 'workadventure') }}
uses: actions/download-artifact@v4
with:
name: back
path: /tmp
- name: Download artifact
if: ${{ (github.event_name != 'pull_request' || github.event.pull_request.head.repo.owner.login != 'workadventure') && (github.event_name == 'pull_request' || github.repository_owner != 'workadventure') }}
uses: actions/download-artifact@v4
with:
name: maps
path: /tmp
- name: Download artifact
if: ${{ (github.event_name != 'pull_request' || github.event.pull_request.head.repo.owner.login != 'workadventure') && (github.event_name == 'pull_request' || github.repository_owner != 'workadventure') }}
uses: actions/download-artifact@v4
with:
name: map-storage
path: /tmp
- name: Download artifact
if: ${{ (github.event_name != 'pull_request' || github.event.pull_request.head.repo.owner.login != 'workadventure') && (github.event_name == 'pull_request' || github.repository_owner != 'workadventure') }}
uses: actions/download-artifact@v4
with:
name: uploader
path: /tmp
- name: Load image
if: ${{ (github.event_name != 'pull_request' || github.event.pull_request.head.repo.owner.login != 'workadventure') && (github.event_name == 'pull_request' || github.repository_owner != 'workadventure') }}
run: |
docker image load --input /tmp/play.tar.gz
docker image load --input /tmp/back.tar.gz
docker image load --input /tmp/maps.tar.gz
docker image load --input /tmp/map-storage.tar.gz
docker image load --input /tmp/uploader.tar.gz
docker image ls -a
- name: Start WorkAdventure
run: docker compose -f docker-compose.yaml -f docker-compose.e2e.yml -f docker-compose.livekit.yaml up -d
- name: Upload test-map
run: sleep 5 && npm run upload-test-map
working-directory: map-storage
- name: Check for no-flaky label
id: check-no-flaky
if: github.event_name == 'pull_request'
run: |
if [[ "${{ contains(github.event.pull_request.labels.*.name, 'no-flaky') }}" == "true" ]]; then
echo "has_no_flaky_label=true" >> $GITHUB_OUTPUT
else
echo "has_no_flaky_label=false" >> $GITHUB_OUTPUT
fi
- name: Run Playwright tests
run: npm run test-prod-like -- ${{ matrix.parameters }} --shard=${{ matrix.shard }}/${{ matrix.nbShards }} --grep-invert "@slow${{ matrix.ignoreTags && matrix.ignoreTags != '' && format('|{0}', matrix.ignoreTags) || '' }}"
working-directory: tests
env:
RENDERER_MODE: ${{ matrix.renderer }}
NO_FLAKY: ${{ steps.check-no-flaky.outputs.has_no_flaky_label }}
IS_FORK: ${{ (github.event_name != 'pull_request' || github.event.pull_request.head.repo.owner.login != 'workadventure') && (github.event_name == 'pull_request' || github.repository_owner != 'workadventure') }}
- name: Display docker compose logs on failure
run: docker compose -f docker-compose.yaml -f docker-compose.e2e.yml logs
if: failure()
- name: Display containers state
run: docker compose -f docker-compose.yaml -f docker-compose.e2e.yml -f docker-compose.livekit.yaml ps
if: failure()
- name: Side-load docker compose logs in the playwright report
run: docker compose -f docker-compose.yaml -f docker-compose.e2e.yml -f docker-compose.livekit.yaml logs > tests/playwright-report/docker-compose.log
if: failure()
- uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report-${{ matrix.project }}-${{ matrix.shard }}-${{ matrix.nbShards }}
path: tests/playwright-report/
retention-days: 30
run-gitlab-saas-tests:
name: "Run Gitlab SaaS tests"
if: ${{ (github.event_name == 'push' && github.ref == 'refs/heads/master') || (github.event_name == 'release') || (github.event_name == 'pull_request' && (contains(github.event.pull_request.labels.*.name, 'deploy') || contains(github.event.pull_request.labels.*.name, 'build') || contains(github.event.pull_request.labels.*.name, 'linked_to_saas_branch'))) }}
runs-on: ubuntu-latest
needs:
- build-back
- build-maps
- build-uploader
- build-map-storage
steps:
- name: Set target branch for GitLab pipeline
id: set-ref
run: |
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
LABELS=$(echo '${{ toJson(github.event.pull_request.labels.*.name) }}')
if echo "$LABELS" | grep -q "linked_to_saas_branch"; then
REF="${{ github.head_ref }}"
elif [[ "${{ github.event.pull_request.base.ref }}" == "develop" ]]; then
REF="develop"
else
REF="master"
fi
else
REF="master"
fi
echo "ref=$REF" >> "$GITHUB_OUTPUT"
- name: Trigger GitLab Pipeline
run: |
REF="${{ steps.set-ref.outputs.ref }}"
echo "Triggering pipeline for ref: $REF"
RESPONSE=$(curl -s -X POST \
"https://git.thecodingmachine.com/api/v4/projects/${{ secrets.GITLAB_SAAS_PROJECT_ID }}/trigger/pipeline" \
-H "Content-Type: application/json" \
-d "{
\"token\": \"${{ secrets.GITLAB_TOKEN_PIPELINE }}\",
\"ref\": \"${REF}\",
\"variables\": {
\"GITHUB_BRANCH_NAME\": \"${{ github.head_ref }}\"
}
}")
PIPELINE_ID=$(echo "$RESPONSE" | jq -r '.id')
if [[ -z "$PIPELINE_ID" || "$PIPELINE_ID" == "null" ]]; then
echo "❌ Failed to trigger GitLab pipeline. Response: $RESPONSE"
exit 1
fi
echo "PIPELINE_ID=$PIPELINE_ID" >> "$GITHUB_ENV"
PIPELINE_URL=$(echo "$RESPONSE" | jq -r '.web_url')
echo "🌐 Pipeline URL: $PIPELINE_URL"
echo "PIPELINE_URL=$PIPELINE_URL" >> "$GITHUB_ENV"
- name: Add pipeline URL to the PR
if: github.event_name == 'pull_request' && env.PIPELINE_URL
uses: hasura/comment-progress@v2.3.0
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
repository: ${{ github.repository }}
number: ${{ github.event.number }}
id: deploy-progress
message: "⏳ GitLab SaaS pipeline in progress... [Check status](${{ env.PIPELINE_URL }})"
fail: false
recreate: true
- name: Long poll GitLab pipeline until finished
id: poll-pipeline
run: |
REF="${{ steps.set-ref.outputs.ref }}"
echo "Polling pipeline for ref: $REF"
PIPELINE_ID="${{ env.PIPELINE_ID }}"
if [[ -z "$PIPELINE_ID" || "$PIPELINE_ID" == "null" ]]; then
echo "❌ No pipeline ID found in environment"
echo "failed=true" >> "$GITHUB_OUTPUT"
exit 0
fi
MAX_ATTEMPTS=120 # 60 minutes with 30 second intervals
ATTEMPT=0
while [ $ATTEMPT -lt $MAX_ATTEMPTS ]; do
RESPONSE=$(curl -s --header "PRIVATE-TOKEN: ${{ secrets.GITLAB_SAAS_READ_API_TOKEN }}" \
"https://git.thecodingmachine.com/api/v4/projects/${{ secrets.GITLAB_SAAS_PROJECT_ID }}/pipelines/${PIPELINE_ID}")
if [[ "$(echo "$RESPONSE" | jq -r '.message')" == "401 Unauthorized" ]]; then
echo "❌ Unauthorized access to GitLab API. Please check the GITLAB_SAAS_READ_API_TOKEN secret."
echo "failed=true" >> "$GITHUB_OUTPUT"
exit 0
fi
if [[ -z "$RESPONSE" || "$RESPONSE" == "null" ]]; then
echo "❌ Failed to get pipeline status. Empty response from GitLab API."
echo "failed=true" >> "$GITHUB_OUTPUT"
exit 0
fi
STATUS=$(echo "$RESPONSE" | jq -r '.status')
if [[ -z "$STATUS" || "$STATUS" == "null" ]]; then
echo "❌ Invalid status response from GitLab API: $RESPONSE"
echo "failed=true" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "⏳ Pipeline status: $STATUS (attempt $ATTEMPT of $MAX_ATTEMPTS)"
case "$STATUS" in
"success")
echo "✅ Pipeline succeeded"
echo "🌐 Pipeline URL: $PIPELINE_URL"
echo "failed=false" >> "$GITHUB_OUTPUT"
exit 0
;;
"failed"|"canceled"|"canceling")
echo "❌ Pipeline ended with status: $STATUS"
echo "🌐 Pipeline URL: $PIPELINE_URL"
echo "failed=true" >> "$GITHUB_OUTPUT"
exit 0
;;
*)
ATTEMPT=$((ATTEMPT + 1))
if [ $ATTEMPT -eq $MAX_ATTEMPTS ]; then
echo "❌ Pipeline timed out after 60 minutes"
echo "🌐 Pipeline URL: $PIPELINE_URL"
echo "failed=true" >> "$GITHUB_OUTPUT"
exit 0
fi
sleep 30
;;
esac
done
- name: Update comment on PR
if: github.event_name == 'pull_request' && env.PIPELINE_URL
uses: hasura/comment-progress@v2.3.0
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
repository: ${{ github.repository }}
number: ${{ github.event.number }}
id: deploy-progress
message: |
${{ steps.poll-pipeline.outputs.failed == 'true' && '❌ GitLab SaaS pipeline failed. ' || '✅ GitLab SaaS pipeline succeeded. ' }}[Check Pipeline](${{ env.PIPELINE_URL }})
fail: ${{ steps.poll-pipeline.outputs.failed == 'true' }}
recreate: true
prod-single-domain-deploy-tests:
name: "Test production docker compose (${{ matrix.shard }}/${{ matrix.nbShards }})"
strategy:
fail-fast: false
matrix:
include:
- shard: 1
nbShards: 2
- shard: 2
nbShards: 2
if: ${{ github.event_name == 'push' || github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'deploy') }}
needs:
- build-play
- build-back
- build-maps
- build-uploader
- build-map-storage
timeout-minutes: 60
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v3
with:
node-version: 22
- name: Install dependencies
run: npm ci
working-directory: tests
- name: Install Playwright
run: npx playwright install --with-deps chromium
working-directory: tests
- name: 'Setup .env file'
run: cp .env.prod.template .env
working-directory: contrib/docker
- uses: rlespinasse/github-slug-action@4.2.3
- name: "Install Room Api client dependencies"
run: npm ci
working-directory: "libs/room-api-clients/room-api-client-js"
- name: "Build Room Api client proto files"
run: npm run ts-proto
working-directory: "libs/room-api-clients/room-api-client-js"
- name: Fill .env file
run: |
sed -i "s/SECRET_KEY=/SECRET_KEY=someSecret/g" .env
sed -i "s/VERSION=master/VERSION=${DOCKER_TAG}/g" .env
sed -i "s/DOMAIN=workadventure.localhost/DOMAIN=play.workadventure.localhost/g" .env
sed -i "s/MAP_STORAGE_AUTHENTICATION_USER=/MAP_STORAGE_AUTHENTICATION_USER=john.doe/g" .env
sed -i "s/MAP_STORAGE_AUTHENTICATION_PASSWORD=/MAP_STORAGE_AUTHENTICATION_PASSWORD=password/g" .env
sed -i "s/ADMIN_API_TOKEN=/ADMIN_API_TOKEN=123/g" .env
sed -i "s/ROOM_API_SECRET_KEY=/ROOM_API_SECRET_KEY=MYAWESOMEKEY/g" .env
sed -i "s/FEATURE_FLAG_BROADCAST_AREAS=/FEATURE_FLAG_BROADCAST_AREAS=true/g" .env
sed -i "s/KLAXOON_ENABLED=false/KLAXOON_ENABLED=true/g" .env
sed -i "s/KLAXOON_CLIENT_ID=/KLAXOON_CLIENT_ID=${{ env.KLAXOON_CLIENT_ID }}/g" .env
sed -i "s/ROOM_API_SECRET_KEY=/ROOM_API_SECRET_KEY=MYAWESOMEKEY/g" .env
sed -i "s/OPENID_PROMPT=/OPENID_PROMPT=login/g" .env
sed -i "s/MAX_USERS_FOR_WEBRTC=4/MAX_USERS_FOR_WEBRTC=3/g" .env
sed -i "s/LIVEKIT_HOST=/LIVEKIT_HOST=https:\/\/livekit.workadventure.localhost/g" .env
sed -i "s/LIVEKIT_API_KEY=/LIVEKIT_API_KEY=devkey/g" .env
sed -i "s/LIVEKIT_API_SECRET=/LIVEKIT_API_SECRET=12345678901234567890123456789012/g" .env
sed -i "s/MAX_PER_GROUP=4/MAX_PER_GROUP=100/g" .env
echo "WOKA_SPEED=3" >> .env
env:
DOCKER_TAG: ${{ github.event_name == 'pull_request' && env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }}
KLAXOON_CLIENT_ID: ${{ secrets.KLAXOON_CLIENT_ID }}
working-directory: contrib/docker
- name: Start WorkAdventure
run: docker compose -f docker-compose.prod.yaml -f tests/docker-compose.test.yaml up -d
env:
DOCKER_TAG: ${{ github.event_name == 'pull_request' && env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }}
working-directory: contrib/docker
- name: Upload test-map
run: |
sed -i "s/http:/https:/g" tests/assets/maps/empty.wam
sleep 10
npm run upload-test-map-single-domain
working-directory: map-storage
- name: Check for no-flaky label
id: check-no-flaky
if: github.event_name == 'pull_request'
run: |
if [[ "${{ contains(github.event.pull_request.labels.*.name, 'no-flaky') }}" == "true" ]]; then
echo "has_no_flaky_label=true" >> $GITHUB_OUTPUT
else
echo "has_no_flaky_label=false" >> $GITHUB_OUTPUT
fi
- name: Run Playwright tests
# Run all tests, except the ones needing to restart Docker and the ones relying on an OIDC server
run: npm run test-single-domain-install -- --shard ${{ matrix.shard }}/${{ matrix.nbShards }}
working-directory: tests
env:
DOCKER_TAG: ${{ github.event_name == 'pull_request' && env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }}
NO_FLAKY: ${{ steps.check-no-flaky.outputs.has_no_flaky_label }}
- name: Display docker compose logs on failure
run: docker compose -f docker-compose.prod.yaml -f tests/docker-compose.test.yaml logs
if: failure()
env:
DOCKER_TAG: ${{ github.event_name == 'pull_request' && env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }}
working-directory: contrib/docker
- name: Display containers state
run: docker compose -f docker-compose.prod.yaml -f tests/docker-compose.test.yaml ps
if: failure()
env:
DOCKER_TAG: ${{ github.event_name == 'pull_request' && env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }}
working-directory: contrib/docker
- name: Side-load docker compose logs in the playwright report
run: docker compose -f docker-compose.prod.yaml -f tests/docker-compose.test.yaml logs > ../../tests/playwright-report/docker-compose.log
if: failure()
env:
DOCKER_TAG: ${{ github.event_name == 'pull_request' && env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }}
working-directory: contrib/docker
- uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report-single-domain-${{ matrix.shard }}-${{ matrix.nbShards }}
path: tests/playwright-report/
retention-days: 30
helm-deploy:
name: "Deploy in Kubernetes"
needs:
- build-play
- build-back
- build-maps
- build-uploader
- build-map-storage
runs-on: ubuntu-24.04
if: ${{ github.event_name == 'push' || github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'deploy') }}
steps:
- name: Checkout
uses: actions/checkout@v2
# Create a slugified value of the branch
- uses: rlespinasse/github-slug-action@4.2.3
- name: Set ADMIN_URL if "deploy-connect-to-admin" label is set
run: echo "ADMIN_API_URL=https://admin-${{ github.event_name == 'pull_request' && env.GITHUB_HEAD_REF_SLUG_URL || env.GITHUB_REF_SLUG_URL }}.test.workadventu.re" >> $GITHUB_ENV
if: ${{ (github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'deploy-connect-to-admin')) || env.GITHUB_REF_SLUG == 'develop' }}
# - name: Write certificate
# run: echo "${CERTS_PRIVATE_KEY}" > secret.key && chmod 0600 secret.key
# env:
# CERTS_PRIVATE_KEY: ${{ secrets.CERTS_PRIVATE_KEY }}
# - name: Download certificate
# run: mkdir secrets && scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i secret.key ubuntu@cert.workadventu.re:./config/live/workadventu.re/* secrets/
# - name: Create namespace
# uses: steebchen/kubectl@v1.0.0
# env:
# KUBE_CONFIG_DATA: ${{ secrets.KUBE_CONFIG_FILE_BASE64 }}
# with:
# args: create namespace workadventure-${{ github.event_name == 'pull_request' && env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }}
# continue-on-error: true
# - name: Delete old certificates in namespace
# uses: steebchen/kubectl@v1.0.0
# env:
# KUBE_CONFIG_DATA: ${{ secrets.KUBE_CONFIG_FILE_BASE64 }}
# with:
# args: -n workadventure-${{ github.event_name == 'pull_request' && env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }} delete secret certificate-tls
# continue-on-error: true
#
# - name: Install certificates in namespace
# uses: steebchen/kubectl@v1.0.0
# env:
# KUBE_CONFIG_DATA: ${{ secrets.KUBE_CONFIG_FILE_BASE64 }}
# with:
# args: -n workadventure-${{ github.event_name == 'pull_request' && env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }} create secret tls certificate-tls --key="secrets/privkey.pem" --cert="secrets/fullchain.pem"
- uses: azure/setup-helm@v4.0.0
with:
#version: '<version>' # default is latest (stable)
token: ${{ secrets.GITHUB_TOKEN }} # only needed if version is 'latest'
id: install
- name: Add comment on PR
if: github.event_name == 'pull_request'
uses: hasura/comment-progress@v2.3.0
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
repository: ${{ github.repository }}
number: ${{ github.event.number }}
id: helm-deploy-progress
message: "⚙️ Deploying environment... "
fail: false
recreate: true
- name: "Install kubeconfig file"
run: mkdir ~/.kube && echo "${KUBE_CONFIG_FILE}" > ~/.kube/config && chmod 0600 ~/.kube/config
env:
KUBE_CONFIG_FILE: ${{ secrets.KUBE_CONFIG_FILE }}
- name: 'Dependencies install'
run: "helm dependencies update"
working-directory: contrib/helm
- name: 'Generate values file'
run: |
echo "
appVersion: \"${DEPLOY_REF}\"
domainName: ${NAMESPACE}.test.workadventu.re
forceRedeploy: true
play:
secretEnv:
ROOM_API_SECRET_KEY: \"password\"
mapstorage:
env:
AUTHENTICATION_USER: \"john.doe\"
secretEnv:
AUTHENTICATION_PASSWORD: \"password\"
maps:
enabled: true
commonEnv:
ENABLE_MAP_EDITOR: true
KLAXOON_ENABLED: true
FEATURE_FLAG_BROADCAST_AREAS: true
YOUTUBE_ENABLED: true
GOOGLE_DRIVE_ENABLED: true
GOOGLE_DOCS_ENABLED: true
GOOGLE_SHEETS_ENABLED: true
GOOGLE_SLIDES_ENABLED: true
DEBUG: \"*\"
commonSecretEnv:
ADMIN_API_TOKEN: \"${ADMIN_API_TOKEN}\"
ADMIN_SOCKETS_TOKEN: \"${ADMIN_SOCKETS_TOKEN}\"
JITSI_ISS: \"${JITSI_ISS}\"
JITSI_URL: \"${JITSI_URL}\"
SECRET_JITSI_KEY: \"${SECRET_JITSI_KEY}\"
TURN_STATIC_AUTH_SECRET: \"${TURN_STATIC_AUTH_SECRET}\"
DEPLOY_REF: \"${DEPLOY_REF}\"
POSTHOG_API_KEY: \"${POSTHOG_API_KEY}\"
POSTHOG_URL: \"${POSTHOG_URL}\"
ENABLE_REPORT_ISSUES_MENU: \"${ENABLE_REPORT_ISSUES_MENU}\"
REPORT_ISSUES_URL: \"${REPORT_ISSUES_URL}\"
LOGROCKET_ID: \"${LOGROCKET_ID}\"
KLAXOON_CLIENT_ID: \"${KLAXOON_CLIENT_ID}\"
GOOGLE_DRIVE_PICKER_CLIENT_ID: \"${GOOGLE_DRIVE_PICKER_CLIENT_ID}\"
GOOGLE_DRIVE_PICKER_APP_ID: \"${GOOGLE_DRIVE_PICKER_APP_ID}\"
MAP_STORAGE_API_TOKEN: \"${MAP_STORAGE_API_TOKEN}\"
LIVEKIT_HOST: \"${LIVEKIT_HOST}\"
LIVEKIT_API_KEY: \"${LIVEKIT_API_KEY}\"
LIVEKIT_API_SECRET: \"${LIVEKIT_API_SECRET}\"
" > values-cd.yaml
working-directory: contrib/helm
env:
KUBE_CONFIG_FILE: ${{ secrets.KUBE_CONFIG_FILE }}
ADMIN_API_TOKEN: ${{ secrets.ADMIN_API_TOKEN }}
ADMIN_SOCKETS_TOKEN: ${{ secrets.ADMIN_SOCKETS_TOKEN }}
JITSI_ISS: ${{ secrets.JITSI_ISS }}
JITSI_URL: ${{ secrets.JITSI_URL }}
SECRET_JITSI_KEY: ${{ secrets.SECRET_JITSI_KEY }}
TURN_STATIC_AUTH_SECRET: ${{ secrets.TURN_STATIC_AUTH_SECRET }}
DEPLOY_REF: ${{ github.event_name == 'pull_request' && env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }}
NAMESPACE: ${{ github.event_name == 'pull_request' && env.GITHUB_HEAD_REF_SLUG_URL || env.GITHUB_REF_SLUG_URL }}
POSTHOG_API_KEY: ${{ secrets.POSTHOG_API_KEY }}
POSTHOG_URL: ${{ secrets.POSTHOG_URL }}
ENABLE_REPORT_ISSUES_MENU: ${{ secrets.ENABLE_REPORT_ISSUES_MENU }}
REPORT_ISSUES_URL: ${{ secrets.REPORT_ISSUES_URL }}
LOGROCKET_ID: ${{ secrets.LOGROCKET_ID }}
KLAXOON_CLIENT_ID: ${{ secrets.KLAXOON_CLIENT_ID }}
GOOGLE_DRIVE_PICKER_CLIENT_ID: ${{ secrets.GOOGLE_DRIVE_PICKER_CLIENT_ID }}
GOOGLE_DRIVE_PICKER_APP_ID: ${{ secrets.GOOGLE_DRIVE_PICKER_APP_ID }}
MAP_STORAGE_API_TOKEN: ${{ secrets.MAP_STORAGE_API_TOKEN }}
LIVEKIT_HOST: ${{ secrets.LIVEKIT_HOST }}
LIVEKIT_API_KEY: ${{ secrets.LIVEKIT_API_KEY }}
LIVEKIT_API_SECRET: ${{ secrets.LIVEKIT_API_SECRET }}
# - name: "Printing values file"
# working-directory: contrib/helm
# run: "cat values-cd.yaml"
- name: "Delete stuck releases"
run: |
if [[ $(helm list -n ${NAMESPACE} --pending | grep pending-upgrade) ]]; then
echo "Found releases in 'pending-upgrade' state in namespace $NAMESPACE. Deleting namespace..."
# Delete the namespace
kubectl delete namespace "$NAMESPACE"
echo "Namespace $NAMESPACE deleted."
else
echo "No releases in 'pending-upgrade' state found in namespace $NAMESPACE."
fi
env:
NAMESPACE: workadventure-${{ github.event_name == 'pull_request' && env.GITHUB_HEAD_REF_SLUG_URL || env.GITHUB_REF_SLUG_URL }}
- name: 'Deploy'
run: "helm upgrade --install --create-namespace -n ${NAMESPACE} --wait -f values.yaml -f values-cd.yaml test ."
working-directory: contrib/helm
env:
NAMESPACE: workadventure-${{ github.event_name == 'pull_request' && env.GITHUB_HEAD_REF_SLUG_URL || env.GITHUB_REF_SLUG_URL }}
- name: "Fix path to assets in WAM test files"
run: find "." -type f -name "*.wam" -exec sed -i "s|http://play.workadventure.localhost|${PLAY_URL}|g" {} \;
working-directory: map-storage/tests
env:
PLAY_URL: "https://play-${{ github.event_name == 'pull_request' && env.GITHUB_HEAD_REF_SLUG_URL || env.GITHUB_REF_SLUG_URL }}.test.workadventu.re"
- name: Upload demo maps in map-storage
run: rm -f tests/assets.zip && cd tests/assets && zip -r ../assets.zip * && curl -F 'file=@../assets.zip' https://map-storage-${NAMESPACE}.test.workadventu.re/upload --basic -u john.doe:password
env:
NAMESPACE: ${{ github.event_name == 'pull_request' && env.GITHUB_HEAD_REF_SLUG_URL || env.GITHUB_REF_SLUG_URL }}
working-directory: map-storage
- name: Update comment on PR
if: github.event_name == 'pull_request'
uses: hasura/comment-progress@v2.3.0
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
repository: ${{ github.repository }}
number: ${{ github.event.number }}
id: helm-deploy-progress
message: "Environment deployed at https://play-${{ env.GITHUB_HEAD_REF_SLUG_URL }}.test.workadventu.re \nTests available at https://maps-${{ env.GITHUB_HEAD_REF_SLUG_URL }}.test.workadventu.re/tests"
fail: false
recreate: true
helm-test:
name: "End to end tests in Kubernetes (${{ matrix.shard }}/${{ matrix.nbShards }})"
needs:
- helm-deploy
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
include:
- shard: 1
nbShards: 2
- shard: 2
nbShards: 2
steps:
- uses: actions/checkout@v2
# Create a slugified value of the branch
- uses: rlespinasse/github-slug-action@4.2.3
- uses: actions/setup-node@v3
with:
node-version: 22
- name: Install dependencies
run: npm ci
working-directory: tests
- name: Install Playwright
run: npx playwright install --with-deps chromium
working-directory: tests
- name: "Install Room Api client dependencies"
run: npm ci
working-directory: "libs/room-api-clients/room-api-client-js"
- name: "Build Room Api client proto files"
run: npm run ts-proto
working-directory: "libs/room-api-clients/room-api-client-js"
- name: "Fix path to assets in WAM test files"
run: find "." -type f -name "*.wam" -exec sed -i "s|http://play.workadventure.localhost|${PLAY_URL}|g" {} \;
working-directory: map-storage/tests
env:
PLAY_URL: "https://play-${{ github.event_name == 'pull_request' && env.GITHUB_HEAD_REF_SLUG_URL || env.GITHUB_REF_SLUG_URL }}.test.workadventu.re"
- name: Create assets.zip needed by the tests
run: rm -f tests/assets.zip && cd tests/assets && zip -r ../assets.zip *
working-directory: map-storage
- name: Check for no-flaky label
id: check-no-flaky
if: github.event_name == 'pull_request'
run: |
if [[ "${{ contains(github.event.pull_request.labels.*.name, 'no-flaky') }}" == "true" ]]; then
echo "has_no_flaky_label=true" >> $GITHUB_OUTPUT
else
echo "has_no_flaky_label=false" >> $GITHUB_OUTPUT
fi
- name: Run Playwright tests
# Run all tests, except the ones needing to restart Docker and the ones relying on an OIDC server
run: npm run test-helm-install -- --shard ${{ matrix.shard }}/${{ matrix.nbShards }}
working-directory: tests
env:
PLAY_URL: "https://play-${{ github.event_name == 'pull_request' && env.GITHUB_HEAD_REF_SLUG_URL || env.GITHUB_REF_SLUG_URL }}.test.workadventu.re"
ROOM_API_HOSTNAME: "room-api-${{ github.event_name == 'pull_request' && env.GITHUB_HEAD_REF_SLUG_URL || env.GITHUB_REF_SLUG_URL }}.test.workadventu.re"
MAP_STORAGE_ENDPOINT: "map-storage-${{ github.event_name == 'pull_request' && env.GITHUB_HEAD_REF_SLUG_URL || env.GITHUB_REF_SLUG_URL }}.test.workadventu.re"
MAPS_DOMAIN: "maps-${{ github.event_name == 'pull_request' && env.GITHUB_HEAD_REF_SLUG_URL || env.GITHUB_REF_SLUG_URL }}.test.workadventu.re"
ROOM_API_SECRET_KEY: "password"
ADMIN_API_TOKEN: ${{ secrets.ADMIN_API_TOKEN }}
MAP_STORAGE_API_TOKEN: ${{ secrets.MAP_STORAGE_API_TOKEN }}
NO_FLAKY: ${{ steps.check-no-flaky.outputs.has_no_flaky_label }}
- uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report-helm-${{ matrix.shard }}-${{ matrix.nbShards }}
path: tests/playwright-report/
retention-days: 30
cleanup:
name: "Cleanup images"
runs-on: ubuntu-latest
needs:
- end-to-end-tests
- prod-single-domain-deploy-tests
- helm-test
# This will fail if the token does not belong to an admin, hence the always
if: always() && ((github.event_name == 'pull_request' && github.event.pull_request.head.repo.owner.login == 'workadventure') || (github.event_name != 'pull_request' && github.repository_owner == 'workadventure'))
continue-on-error: true
steps:
- name: Prune play
uses: vlaurin/action-ghcr-prune@v0.6.0
with:
token: ${{ secrets.GITHUB_TOKEN }}
organization: workadventure
container: play-dev-build
dry-run: false # Dry-run first, then change to `false`
keep-younger-than: 7 # days
keep-last: 5
prune-untagged: true
prune-tags-regexes: ".*"
- name: Prune back
uses: vlaurin/action-ghcr-prune@v0.6.0
with:
token: ${{ secrets.GITHUB_TOKEN }}
organization: workadventure
dry-run: false # Dry-run first, then change to `false`
container: back-dev-build
keep-younger-than: 7 # days
keep-last: 5
prune-untagged: true
prune-tags-regexes: ".*"
- name: Prune map-storage
uses: vlaurin/action-ghcr-prune@v0.6.0
with:
token: ${{ secrets.GITHUB_TOKEN }}
organization: workadventure
container: map-storage-dev-build
dry-run: false # Dry-run first, then change to `false`
keep-younger-than: 7 # days
keep-last: 5
prune-untagged: true
prune-tags-regexes: ".*"
- name: Prune maps
uses: vlaurin/action-ghcr-prune@v0.6.0
with:
token: ${{ secrets.GITHUB_TOKEN }}
organization: workadventure
container: maps-dev-build
dry-run: false # Dry-run first, then change to `false`
keep-younger-than: 7 # days
keep-last: 5
prune-untagged: true
prune-tags-regexes: ".*"
- name: Prune uploader
uses: vlaurin/action-ghcr-prune@v0.6.0
with:
token: ${{ secrets.GITHUB_TOKEN }}
organization: workadventure
container: uploader-dev-build
dry-run: false # Dry-run first, then change to `false`
keep-younger-than: 7 # days
keep-last: 5
prune-untagged: true
prune-tags-regexes: ".*"