fix(presence): update connections on heartbeat and remove them when stale #47134
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| release: | |
| types: [published] | |
| pull_request: | |
| branches: '**' | |
| paths-ignore: | |
| - '**.md' | |
| push: | |
| branches: | |
| - develop | |
| paths-ignore: | |
| - '**.md' | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} | |
| cancel-in-progress: true | |
| env: | |
| TOOL_NODE_FLAGS: ${{ vars.TOOL_NODE_FLAGS }} | |
| jobs: | |
| release-versions: | |
| name: ⚙️ Variables Setup | |
| runs-on: ubuntu-24.04-arm | |
| outputs: | |
| release: ${{ steps.by-tag.outputs.release }} | |
| latest-release: ${{ steps.latest.outputs.latest-release }} | |
| gh-docker-tag: ${{ steps.docker.outputs.gh-docker-tag }} | |
| lowercase-repo: ${{ steps.var.outputs.lowercase-repo }} | |
| node-version: ${{ steps.var.outputs.node-version }} | |
| deno-version: ${{ steps.var.outputs.deno-version }} | |
| source-hash: ${{ steps.source.outputs.hash }} | |
| # this is 100% intentional, secrets are not available for forks, so ee-tests will always fail | |
| # to avoid this, we are using a dummy license, expiring at 2026-07-01 | |
| enterprise-license: Uo7Jcr6WW0XYA8ydHd+Sk6pZ9/0V6dIASnyTwvUrNym/zJg2Ma3eYNKkC8osXLCc72y1ahohnWY7/+7IYkvono3GYXQR+IGvYbbrVgNR6OjMahd9P/odHZL1GFTm2qHrEL5Hh/XEOG+YluFeRdWPzCizQlp4zGGOi0+PkQo096TR9NVCLrsErVl2MW1WM6ZM1W5EUJG9pKly4BQnaOTUAlor1im6i8qPTDCKrISZfLiZEWuQKaPW/GE3mRKjQNjDh0CabX1N2S880pRRGoozBYAnp2NmFfrQW0+5ihKisBTIeMbMZ7K5NE5PkYU1nhQDcc+rpDHtwG9Ceg5X0J+oea3UfrPTmDON2aSI0iO22kvL6G7QI3fyrEIvJrMbxcNKxAFeQYgnjisw/b06+chWSG4jG686Fx58XrVS87dFhWL9WoGltsk1dJCntUQvI1sX6zOfpvyg1iWRnHfYDOrwoWlX57XMm29fWineEoqnOOTOVnA/uP+DKEhercQ9Xuo7Cr6zJxpQpwd03e7ODVjiEbTDqlkZE687rmxRCD4Wmu8L86WIl2xSEIajKLX301Ww5mz/FdLqk+Mg32lkW66W3azQKvJ1440NBrYxhpJ+dl9vSFMb3s1+xnz1cYUbjUcq9mARvORcgy5mLwKulmqT6Sq0Uvbv10YCO0TW0beXYW8= | |
| steps: | |
| - name: Github Info | |
| run: | | |
| echo "GITHUB_ACTION: $GITHUB_ACTION" | |
| echo "GITHUB_ACTOR: $GITHUB_ACTOR" | |
| echo "GITHUB_REF: $GITHUB_REF" | |
| echo "GITHUB_HEAD_REF: $GITHUB_HEAD_REF" | |
| echo "GITHUB_BASE_REF: $GITHUB_BASE_REF" | |
| echo "github.event_name: ${{ github.event_name }}" | |
| cat $GITHUB_EVENT_PATH | |
| - uses: actions/checkout@v6 | |
| # with: | |
| # sparse-checkout: | | |
| # package.json | |
| # .tool-versions | |
| # sparse-checkout-cone-mode: false | |
| # ref: ${{ github.ref }} | |
| - id: source | |
| run: | | |
| ls -la | |
| tar -cf /tmp/RocketChat-source.tar \ | |
| --sort=name \ | |
| --owner=0 --group=0 \ | |
| --mtime='1970-01-01' \ | |
| --exclude='.github' \ | |
| --exclude='.git' \ | |
| . | |
| SOURCE_HASH=$(sha256sum /tmp/RocketChat-source.tar | awk '{ print $1 }')-v8 | |
| # Uncomment the following line to include the run ID in the hash and disable caching between runs | |
| # SOURCE_HASH=$(sha256sum /tmp/RocketChat-source.tar | awk '{ print $1 }')-${{ github.run_id }} | |
| echo hash=${SOURCE_HASH} | |
| echo hash=${SOURCE_HASH} >> $GITHUB_OUTPUT | |
| - id: var | |
| run: | | |
| LOWERCASE_REPOSITORY=$(echo "${{ github.repository_owner }}" | tr "[:upper:]" "[:lower:]") | |
| echo "LOWERCASE_REPOSITORY: ${LOWERCASE_REPOSITORY}" | |
| echo "lowercase-repo=${LOWERCASE_REPOSITORY}" >> $GITHUB_OUTPUT | |
| NODE_VERSION=$(node -p "require('./package.json').engines.node") | |
| echo "NODE_VERSION: ${NODE_VERSION}" | |
| echo "node-version=${NODE_VERSION}" >> $GITHUB_OUTPUT | |
| DENO_VERSION=$(awk '$1=="deno"{ print $2 }' .tool-versions) | |
| echo "DENO_VERSION: ${DENO_VERSION}" | |
| echo "deno-version=${DENO_VERSION}" >> $GITHUB_OUTPUT | |
| - id: by-tag | |
| run: | | |
| if echo "$GITHUB_REF_NAME" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$' ; then | |
| RELEASE="latest" | |
| elif echo "$GITHUB_REF_NAME" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+-rc\.[0-9]+$' ; then | |
| RELEASE="release-candidate" | |
| fi | |
| echo "RELEASE: ${RELEASE}" | |
| echo "release=${RELEASE}" >> $GITHUB_OUTPUT | |
| - id: latest | |
| run: | | |
| LATEST_RELEASE="$( | |
| git -c 'versionsort.suffix=-' ls-remote -t --exit-code --refs --sort=-v:refname "https://github.com/$GITHUB_REPOSITORY" '*' | | |
| awk -F/ '$NF !~ /rc|beta/ { print $NF; exit }' | |
| )" | |
| echo "LATEST_RELEASE: ${LATEST_RELEASE}" | |
| echo "latest-release=${LATEST_RELEASE}" >> $GITHUB_OUTPUT | |
| - id: docker | |
| run: | | |
| if [[ '${{ github.event_name }}' == 'pull_request' ]]; then | |
| DOCKER_TAG="pr-${{ github.event.number }}" | |
| else | |
| DOCKER_TAG=$GITHUB_REF_NAME | |
| fi | |
| echo "DOCKER_TAG: ${DOCKER_TAG}" | |
| echo "gh-docker-tag=${DOCKER_TAG}" >> $GITHUB_OUTPUT | |
| notify-draft-services: | |
| name: 🚀 Notify external services - draft | |
| runs-on: ubuntu-24.04-arm | |
| needs: [release-versions] | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| sparse-checkout: | | |
| package.json | |
| sparse-checkout-cone-mode: false | |
| ref: ${{ github.ref }} | |
| - name: Register release on cloud as Draft | |
| if: github.event_name == 'release' | |
| env: | |
| UPDATE_TOKEN: ${{ secrets.UPDATE_TOKEN }} | |
| run: | | |
| REPO_VERSION=$(node -p "require('./package.json').version") | |
| if [[ '${{ github.event_name }}' = 'release' ]]; then | |
| GIT_TAG="${GITHUB_REF#*tags/}" | |
| GIT_BRANCH="" | |
| ARTIFACT_NAME="${REPO_VERSION}" | |
| RC_VERSION=$GIT_TAG | |
| if [[ '${{ needs.release-versions.outputs.release }}' = 'release-candidate' ]]; then | |
| RC_RELEASE=candidate | |
| elif [[ '${{ needs.release-versions.outputs.release }}' = 'latest' ]]; then | |
| RC_RELEASE=stable | |
| fi | |
| else | |
| GIT_TAG="" | |
| GIT_BRANCH="${GITHUB_REF#*heads/}" | |
| ARTIFACT_NAME="${REPO_VERSION}.$GITHUB_SHA" | |
| RC_VERSION="${REPO_VERSION}" | |
| RC_RELEASE=develop | |
| fi; | |
| curl -H "Content-Type: application/json" -H "X-Update-Token: $UPDATE_TOKEN" -d \ | |
| "{\"nodeVersion\": \"${{ needs.release-versions.outputs.node-version }}\", \"denoVersion\": \"${{ needs.release-versions.outputs.deno-version }}\", \"compatibleMongoVersions\": [\"5\", \"6\", \"7\", \"8\"], \"commit\": \"$GITHUB_SHA\", \"tag\": \"$RC_VERSION\", \"branch\": \"$GIT_BRANCH\", \"artifactName\": \"$ARTIFACT_NAME\", \"releaseType\": \"draft\", \"draftAs\": \"$RC_RELEASE\"}" \ | |
| https://releases.rocket.chat/update | |
| packages-build: | |
| name: 📦 Build Packages | |
| needs: [release-versions, notify-draft-services] | |
| runs-on: ubuntu-24.04-arm | |
| steps: | |
| - name: Cache build | |
| uses: actions/cache@v4 | |
| id: packages-cache-build | |
| with: | |
| path: | | |
| /tmp/RocketChat-packages-build.tar.gz | |
| key: ${{ runner.arch }}-${{ runner.os }}-packages-build-${{ needs.release-versions.outputs.source-hash }} | |
| - name: Debug cache-hit | |
| run: echo "cache-hit=${{ steps.packages-cache-build.outputs.cache-hit }}" | |
| - name: Set Swap Space | |
| uses: pierotofy/set-swap-space@master | |
| if: steps.packages-cache-build.outputs.cache-hit != 'true' | |
| with: | |
| swap-size-gb: 4 | |
| - uses: actions/checkout@v6 | |
| if: steps.packages-cache-build.outputs.cache-hit != 'true' | |
| - name: Setup NodeJS | |
| uses: ./.github/actions/setup-node | |
| if: steps.packages-cache-build.outputs.cache-hit != 'true' | |
| with: | |
| node-version: ${{ needs.release-versions.outputs.node-version }} | |
| deno-version: ${{ needs.release-versions.outputs.deno-version }} | |
| cache-modules: true | |
| install: true | |
| NPM_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| HARDENED_MODE: '1' | |
| - name: Cache vite | |
| uses: actions/cache@v4 | |
| if: steps.packages-cache-build.outputs.cache-hit != 'true' | |
| with: | |
| path: ./node_modules/.vite | |
| key: vite-local-cache-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('package.json') }} | |
| restore-keys: | | |
| vite-local-cache-${{ runner.arch }}-${{ runner.os }}- | |
| - uses: rharkor/[email protected] | |
| if: steps.packages-cache-build.outputs.cache-hit != 'true' | |
| - name: Build Rocket.Chat Packages | |
| if: steps.packages-cache-build.outputs.cache-hit != 'true' | |
| run: yarn build | |
| - name: Archive packages build output | |
| if: steps.packages-cache-build.outputs.cache-hit != 'true' | |
| run: | | |
| tar -czf /tmp/RocketChat-packages-build.tar.gz \ | |
| $(git ls-files -oi --exclude-standard -- ':(exclude)node_modules/*' ':(exclude)**/node_modules/*' ':(exclude)**/.meteor/*' ':(exclude)**/.deno-cache/*' ':(exclude)**/.turbo/*' ':(exclude).turbo/*' ':(exclude)**/.yarn/*' ':(exclude).yarn/*' ':(exclude).git/*') | |
| - name: Upload packages build artifact | |
| uses: actions/upload-artifact@v5 | |
| with: | |
| name: packages-build | |
| path: /tmp/RocketChat-packages-build.tar.gz | |
| retention-days: 5 | |
| - name: Store turbo build | |
| if: steps.packages-cache-build.outputs.cache-hit != 'true' | |
| uses: actions/upload-artifact@v5 | |
| with: | |
| name: turbo-build | |
| path: .turbo/cache | |
| overwrite: true | |
| include-hidden-files: true | |
| build: | |
| name: 📦 Meteor Build (${{ matrix.type }}) | |
| needs: [release-versions, packages-build] | |
| runs-on: ubuntu-24.04-arm | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| type: | |
| - production | |
| - coverage | |
| exclude: | |
| - type: ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'production' || '' }} | |
| steps: | |
| - name: Collect Workflow Telemetry | |
| uses: catchpoint/workflow-telemetry-action@v2 | |
| with: | |
| theme: dark | |
| job_summary: true | |
| comment_on_pr: false | |
| - uses: actions/checkout@v6 | |
| - uses: ./.github/actions/meteor-build | |
| with: | |
| node-version: ${{ needs.release-versions.outputs.node-version }} | |
| deno-version: ${{ needs.release-versions.outputs.deno-version }} | |
| source-hash: ${{ needs.release-versions.outputs.source-hash }} | |
| type: ${{ matrix.type }} | |
| build-gh-docker: | |
| name: 🚢 Build Docker | |
| needs: [build, release-versions] | |
| runs-on: ubuntu-24.04${{ matrix.arch == 'arm64' && '-arm' || '' }} | |
| env: | |
| DOCKER_TAG: ${{ needs.release-versions.outputs.gh-docker-tag }}-${{ matrix.arch }} | |
| LOWERCASE_REPOSITORY: ${{ needs.release-versions.outputs.lowercase-repo }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| arch: [arm64, amd64] | |
| service: | |
| [ | |
| [authorization-service, queue-worker-service, ddp-streamer-service], | |
| [account-service, presence-service, stream-hub-service, omnichannel-transcript-service], | |
| [rocketchat], | |
| ] | |
| type: | |
| # if running in a PR build with coverage | |
| - ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }} | |
| include: | |
| # if not, build with coverage for tests | |
| - arch: amd64 | |
| service: [rocketchat] | |
| type: coverage | |
| - arch: arm64 | |
| service: [rocketchat] | |
| type: coverage | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Restore packages build | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: packages-build | |
| path: /tmp | |
| - name: Unpack packages build | |
| shell: bash | |
| run: | | |
| tar -xzf /tmp/RocketChat-packages-build.tar.gz -C . | |
| # we only build and publish the actual docker images if not a PR from a fork | |
| - name: Image ${{ matrix.service[0] }} | |
| uses: ./.github/actions/build-docker | |
| if: (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop') && github.actor != 'dependabot[bot]' | |
| env: | |
| # add suffix for the extra images with coverage if building for production | |
| DOCKER_TAG_SUFFIX_ROCKETCHAT: ${{ matrix.type == 'coverage' && (github.event_name == 'release' || github.ref == 'refs/heads/develop') && '-cov' || '' }} | |
| with: | |
| CR_USER: ${{ secrets.CR_USER }} | |
| CR_PAT: ${{ secrets.CR_PAT }} | |
| deno-version: ${{ needs.release-versions.outputs.deno-version }} | |
| arch: ${{ matrix.arch }} | |
| service: ${{ matrix.service[0] }} | |
| type: ${{ matrix.type }} | |
| - name: Image ${{ matrix.service[1] || '"skipped"' }} | |
| uses: ./.github/actions/build-docker | |
| if: matrix.service[1] && (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop') && github.actor != 'dependabot[bot]' | |
| env: | |
| DOCKER_TAG_SUFFIX_ROCKETCHAT: ${{ matrix.type == 'coverage' && '-cov' || '' }} | |
| with: | |
| CR_USER: ${{ secrets.CR_USER }} | |
| CR_PAT: ${{ secrets.CR_PAT }} | |
| deno-version: ${{ needs.release-versions.outputs.deno-version }} | |
| arch: ${{ matrix.arch }} | |
| service: ${{ matrix.service[1] }} | |
| type: ${{ matrix.type }} | |
| setup-docker: false | |
| - name: Image ${{ matrix.service[2] || '"skipped"' }} | |
| uses: ./.github/actions/build-docker | |
| if: matrix.service[2] && (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop') && github.actor != 'dependabot[bot]' | |
| env: | |
| DOCKER_TAG_SUFFIX_ROCKETCHAT: ${{ matrix.type == 'coverage' && '-cov' || '' }} | |
| with: | |
| CR_USER: ${{ secrets.CR_USER }} | |
| CR_PAT: ${{ secrets.CR_PAT }} | |
| deno-version: ${{ needs.release-versions.outputs.deno-version }} | |
| arch: ${{ matrix.arch }} | |
| service: ${{ matrix.service[2] }} | |
| type: ${{ matrix.type }} | |
| setup-docker: false | |
| - name: Image ${{ matrix.service[3] || '"skipped"' }} | |
| uses: ./.github/actions/build-docker | |
| if: matrix.service[3] && (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop') && github.actor != 'dependabot[bot]' | |
| env: | |
| DOCKER_TAG_SUFFIX_ROCKETCHAT: ${{ matrix.type == 'coverage' && '-cov' || '' }} | |
| with: | |
| CR_USER: ${{ secrets.CR_USER }} | |
| CR_PAT: ${{ secrets.CR_PAT }} | |
| deno-version: ${{ needs.release-versions.outputs.deno-version }} | |
| arch: ${{ matrix.arch }} | |
| service: ${{ matrix.service[3] }} | |
| type: ${{ matrix.type }} | |
| setup-docker: false | |
| build-gh-docker-publish: | |
| name: 🚢 Publish Docker Images (ghcr.io) | |
| needs: [build-gh-docker, release-versions] | |
| runs-on: ubuntu-24.04-arm | |
| env: | |
| DOCKER_TAG: ${{ needs.release-versions.outputs.gh-docker-tag }} | |
| LOWERCASE_REPOSITORY: ${{ needs.release-versions.outputs.lowercase-repo }} | |
| steps: | |
| - uses: actions/checkout@v6 | |
| if: github.actor != 'dependabot[bot]' && (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop') | |
| with: | |
| sparse-checkout: | | |
| docker-compose-ci.yml | |
| sparse-checkout-cone-mode: false | |
| ref: ${{ github.ref }} | |
| - name: Login to GitHub Container Registry | |
| if: github.actor != 'dependabot[bot]' && (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop') | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ secrets.CR_USER }} | |
| password: ${{ secrets.CR_PAT }} | |
| - name: Download manifests | |
| if: github.actor != 'dependabot[bot]' && (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop') | |
| uses: actions/download-artifact@v6 | |
| with: | |
| pattern: manifests-* | |
| path: /tmp/manifests | |
| merge-multiple: true | |
| - name: Create and push multi-arch manifests | |
| if: github.actor != 'dependabot[bot]' && (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop') | |
| run: | | |
| set -o xtrace | |
| shopt -s nullglob | |
| for service_dir in /tmp/manifests/*; do | |
| [[ -d "$service_dir" ]] || continue | |
| service="$(basename "$service_dir")" | |
| echo "Creating manifest for $service" | |
| # Extract digests from manifest.json files | |
| mapfile -t refs < <( | |
| find "$service_dir" -type f -name 'manifest.json' -print0 \ | |
| | xargs -0 -I{} jq -r '.Descriptor.digest as $digest | .Ref | split("@")[0] + "@" + $digest' {} | |
| ) | |
| echo "Digest for ${service}: ${refs[@]}" | |
| # Get image name from docker-compose-ci.yml since rocketchat image is different from service name (rocket.chat) | |
| if [ "$service" == "rocketchat-cov" ]; then | |
| IMAGE=$(docker compose -f docker-compose-ci.yml config --format json 2>/dev/null | jq -r --arg s "rocketchat" '.services[$s].image')-cov | |
| else | |
| IMAGE=$(docker compose -f docker-compose-ci.yml config --format json 2>/dev/null | jq -r --arg s "$service" '.services[$s].image') | |
| fi | |
| echo $IMAGE | |
| docker buildx imagetools create \ | |
| --debug \ | |
| --annotation "manifest-descriptor:org.opencontainers.image.description=Build run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" \ | |
| --tag "${IMAGE}" \ | |
| --tag "${IMAGE}-gha-run-${{ github.run_id }}" \ | |
| ${refs[@]} | |
| done | |
| track-image-sizes: | |
| name: 📦 Track Image Sizes | |
| needs: [build-gh-docker-publish, release-versions] | |
| runs-on: ubuntu-24.04-arm | |
| if: github.event_name == 'pull_request' || github.ref == 'refs/heads/develop' | |
| permissions: | |
| pull-requests: write | |
| contents: write | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Track Docker image sizes | |
| uses: ./.github/actions/docker-image-size-tracker | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| ci-pat: ${{ secrets.CI_PAT }} | |
| registry: ghcr.io | |
| repository: ${{ needs.release-versions.outputs.lowercase-repo }} | |
| tag: ${{ needs.release-versions.outputs.gh-docker-tag }} | |
| baseline-tag: develop | |
| checks: | |
| needs: [release-versions, packages-build] | |
| name: 🔎 Code Check | |
| uses: ./.github/workflows/ci-code-check.yml | |
| with: | |
| node-version: ${{ needs.release-versions.outputs.node-version }} | |
| deno-version: ${{ needs.release-versions.outputs.deno-version }} | |
| test-storybook: | |
| name: 🔨 Test Storybook | |
| needs: [packages-build, release-versions] | |
| uses: ./.github/workflows/ci-test-storybook.yml | |
| with: | |
| node-version: ${{ needs.release-versions.outputs.node-version }} | |
| deno-version: ${{ needs.release-versions.outputs.deno-version }} | |
| secrets: | |
| CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} | |
| test-unit: | |
| name: 🔨 Test Unit | |
| needs: [packages-build, release-versions] | |
| uses: ./.github/workflows/ci-test-unit.yml | |
| with: | |
| node-version: ${{ needs.release-versions.outputs.node-version }} | |
| deno-version: ${{ needs.release-versions.outputs.deno-version }} | |
| enterprise-license: ${{ needs.release-versions.outputs.enterprise-license }} | |
| secrets: | |
| CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} | |
| test-api: | |
| name: 🔨 Test API (CE) | |
| needs: [checks, build-gh-docker-publish, release-versions] | |
| uses: ./.github/workflows/ci-test-e2e.yml | |
| with: | |
| type: api | |
| release: ce | |
| node-version: ${{ needs.release-versions.outputs.node-version }} | |
| deno-version: ${{ needs.release-versions.outputs.deno-version }} | |
| lowercase-repo: ${{ needs.release-versions.outputs.lowercase-repo }} | |
| gh-docker-tag: ${{ needs.release-versions.outputs.gh-docker-tag }} | |
| secrets: | |
| CR_USER: ${{ secrets.CR_USER }} | |
| CR_PAT: ${{ secrets.CR_PAT }} | |
| test-ui: | |
| name: 🔨 Test UI (CE) | |
| needs: [checks, build-gh-docker-publish, release-versions] | |
| uses: ./.github/workflows/ci-test-e2e.yml | |
| with: | |
| type: ui | |
| release: ce | |
| transporter: 'nats://nats:4222' | |
| enterprise-license: ${{ needs.release-versions.outputs.enterprise-license }} | |
| shard: '[1, 2, 3, 4]' | |
| total-shard: 4 | |
| node-version: ${{ needs.release-versions.outputs.node-version }} | |
| deno-version: ${{ needs.release-versions.outputs.deno-version }} | |
| lowercase-repo: ${{ needs.release-versions.outputs.lowercase-repo }} | |
| gh-docker-tag: ${{ needs.release-versions.outputs.gh-docker-tag }} | |
| retries: ${{ (github.event_name == 'release' || github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/master') && 2 || 0 }} | |
| secrets: | |
| CR_USER: ${{ secrets.CR_USER }} | |
| CR_PAT: ${{ secrets.CR_PAT }} | |
| QASE_API_TOKEN: ${{ secrets.QASE_API_TOKEN }} | |
| REPORTER_ROCKETCHAT_API_KEY: ${{ secrets.REPORTER_ROCKETCHAT_API_KEY }} | |
| REPORTER_ROCKETCHAT_URL: ${{ secrets.REPORTER_ROCKETCHAT_URL }} | |
| REPORTER_JIRA_ROCKETCHAT_API_KEY: ${{ secrets.REPORTER_JIRA_ROCKETCHAT_API_KEY }} | |
| test-api-ee: | |
| name: 🔨 Test API (EE) | |
| needs: [checks, build-gh-docker-publish, release-versions] | |
| uses: ./.github/workflows/ci-test-e2e.yml | |
| with: | |
| type: api | |
| release: ee | |
| transporter: 'nats://nats:4222' | |
| enterprise-license: ${{ needs.release-versions.outputs.enterprise-license }} | |
| mongodb-version: "['5.0', '8.2']" | |
| coverage: '8.2' | |
| node-version: ${{ needs.release-versions.outputs.node-version }} | |
| deno-version: ${{ needs.release-versions.outputs.deno-version }} | |
| lowercase-repo: ${{ needs.release-versions.outputs.lowercase-repo }} | |
| gh-docker-tag: ${{ needs.release-versions.outputs.gh-docker-tag }} | |
| secrets: | |
| CR_USER: ${{ secrets.CR_USER }} | |
| CR_PAT: ${{ secrets.CR_PAT }} | |
| test-ui-ee: | |
| name: 🔨 Test UI (EE) | |
| needs: [checks, build-gh-docker-publish, release-versions] | |
| uses: ./.github/workflows/ci-test-e2e.yml | |
| with: | |
| type: ui | |
| release: ee | |
| transporter: 'nats://nats:4222' | |
| enterprise-license: ${{ needs.release-versions.outputs.enterprise-license }} | |
| shard: '[1, 2, 3, 4, 5]' | |
| total-shard: 5 | |
| mongodb-version: "['5.0']" | |
| node-version: ${{ needs.release-versions.outputs.node-version }} | |
| deno-version: ${{ needs.release-versions.outputs.deno-version }} | |
| lowercase-repo: ${{ needs.release-versions.outputs.lowercase-repo }} | |
| gh-docker-tag: ${{ needs.release-versions.outputs.gh-docker-tag }} | |
| retries: ${{ (github.event_name == 'release' || github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/master') && 2 || 0 }} | |
| secrets: | |
| CR_USER: ${{ secrets.CR_USER }} | |
| CR_PAT: ${{ secrets.CR_PAT }} | |
| QASE_API_TOKEN: ${{ secrets.QASE_API_TOKEN }} | |
| REPORTER_ROCKETCHAT_API_KEY: ${{ secrets.REPORTER_ROCKETCHAT_API_KEY }} | |
| REPORTER_ROCKETCHAT_URL: ${{ secrets.REPORTER_ROCKETCHAT_URL }} | |
| CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} | |
| REPORTER_JIRA_ROCKETCHAT_API_KEY: ${{ secrets.REPORTER_JIRA_ROCKETCHAT_API_KEY }} | |
| test-ui-ee-watcher: | |
| name: 🔨 Test UI (EE) | |
| needs: [checks, build-gh-docker-publish, release-versions] | |
| uses: ./.github/workflows/ci-test-e2e.yml | |
| with: | |
| type: ui | |
| release: ee | |
| transporter: 'nats://nats:4222' | |
| enterprise-license: ${{ needs.release-versions.outputs.enterprise-license }} | |
| shard: '[1, 2, 3, 4, 5]' | |
| total-shard: 5 | |
| mongodb-version: "['8.2']" | |
| coverage: '8.2' | |
| node-version: ${{ needs.release-versions.outputs.node-version }} | |
| deno-version: ${{ needs.release-versions.outputs.deno-version }} | |
| lowercase-repo: ${{ needs.release-versions.outputs.lowercase-repo }} | |
| gh-docker-tag: ${{ needs.release-versions.outputs.gh-docker-tag }} | |
| retries: ${{ (github.event_name == 'release' || github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/master') && 2 || 0 }} | |
| db-watcher-disabled: 'false' | |
| secrets: | |
| CR_USER: ${{ secrets.CR_USER }} | |
| CR_PAT: ${{ secrets.CR_PAT }} | |
| QASE_API_TOKEN: ${{ secrets.QASE_API_TOKEN }} | |
| REPORTER_ROCKETCHAT_API_KEY: ${{ secrets.REPORTER_ROCKETCHAT_API_KEY }} | |
| REPORTER_ROCKETCHAT_URL: ${{ secrets.REPORTER_ROCKETCHAT_URL }} | |
| CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} | |
| REPORTER_JIRA_ROCKETCHAT_API_KEY: ${{ secrets.REPORTER_JIRA_ROCKETCHAT_API_KEY }} | |
| test-federation-matrix: | |
| name: 🔨 Test Federation Matrix | |
| needs: [checks, build-gh-docker-publish, packages-build, release-versions] | |
| runs-on: ubuntu-24.04-arm | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Setup NodeJS | |
| uses: ./.github/actions/setup-node | |
| with: | |
| node-version: ${{ needs.release-versions.outputs.node-version }} | |
| deno-version: ${{ needs.release-versions.outputs.deno-version }} | |
| cache-modules: true | |
| install: true | |
| - uses: rharkor/[email protected] | |
| - name: Restore turbo build | |
| uses: actions/download-artifact@v6 | |
| continue-on-error: true | |
| with: | |
| name: turbo-build | |
| path: .turbo/cache | |
| - name: Build packages | |
| run: yarn build | |
| - name: Login to GitHub Container Registry | |
| if: (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop') && github.actor != 'dependabot[bot]' | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ secrets.CR_USER }} | |
| password: ${{ secrets.CR_PAT }} | |
| - name: Configure /etc/hosts for federation services | |
| run: | | |
| sudo -- sh -c "echo '127.0.0.1 hs1' >> /etc/hosts" | |
| sudo -- sh -c "echo '127.0.0.1 rc1' >> /etc/hosts" | |
| - name: Run federation integration tests with pre-built image | |
| working-directory: ./ee/packages/federation-matrix | |
| env: | |
| ROCKETCHAT_IMAGE: ghcr.io/${{ needs.release-versions.outputs.lowercase-repo }}/rocket.chat:${{ needs.release-versions.outputs.gh-docker-tag }} | |
| ENTERPRISE_LICENSE_RC1: ${{ secrets.ENTERPRISE_LICENSE_RC1 }} | |
| QASE_TESTOPS_JEST_API_TOKEN: ${{ secrets.QASE_TESTOPS_JEST_API_TOKEN }} | |
| run: yarn test:integration --image "${ROCKETCHAT_IMAGE}" | |
| report-coverage: | |
| name: 📊 Report Coverage | |
| runs-on: ubuntu-24.04 | |
| needs: [release-versions, test-api-ee, test-ui-ee, test-ui-ee-watcher] | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Use Node.js | |
| uses: actions/[email protected] | |
| with: | |
| node-version: ${{ needs.release-versions.outputs.node-version }} | |
| - name: Restore coverage folder | |
| uses: actions/download-artifact@v6 | |
| with: | |
| pattern: coverage-* | |
| path: /tmp/coverage | |
| merge-multiple: true | |
| - name: Generate lcov report | |
| run: | | |
| set -o xtrace | |
| npx nyc report --reporter=lcovonly --report-dir=/tmp/coverage_report/api --temp-dir=/tmp/coverage/api | |
| npx nyc report --reporter=lcovonly --report-dir=/tmp/coverage_report/ui --temp-dir=/tmp/coverage/ui | |
| - name: Store coverage-reports | |
| uses: actions/upload-artifact@v5 | |
| with: | |
| name: reports-coverage | |
| path: /tmp/coverage_report | |
| include-hidden-files: true | |
| - name: Report API coverage | |
| uses: codecov/codecov-action@v3 | |
| with: | |
| files: /tmp/coverage_report/api/lcov.info | |
| working-directory: . | |
| flags: e2e-api | |
| verbose: true | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| - name: Report UI coverage | |
| uses: codecov/codecov-action@v3 | |
| with: | |
| files: /tmp/coverage_report/ui/lcov.info | |
| working-directory: . | |
| flags: e2e | |
| verbose: true | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| tests-done: | |
| name: ✅ Tests Done | |
| runs-on: ubuntu-24.04-arm | |
| needs: [checks, test-unit, test-api, test-ui, test-api-ee, test-ui-ee, test-ui-ee-watcher, test-federation-matrix] | |
| if: always() | |
| steps: | |
| - name: Test finish aggregation | |
| run: | | |
| if [[ '${{ needs.checks.result }}' != 'success' ]]; then | |
| exit 1 | |
| fi | |
| if [[ '${{ needs.test-unit.result }}' != 'success' ]]; then | |
| exit 1 | |
| fi | |
| if [[ '${{ needs.test-api.result }}' != 'success' ]]; then | |
| exit 1 | |
| fi | |
| if [[ '${{ needs.test-ui.result }}' != 'success' ]]; then | |
| exit 1 | |
| fi | |
| if [[ '${{ needs.test-api-ee.result }}' != 'success' ]]; then | |
| exit 1 | |
| fi | |
| if [[ '${{ needs.test-ui-ee.result }}' != 'success' ]]; then | |
| exit 1 | |
| fi | |
| if [[ '${{ needs.test-ui-ee-watcher.result }}' != 'success' ]]; then | |
| exit 1 | |
| fi | |
| if [[ '${{ needs.test-federation-matrix.result }}' != 'success' ]]; then | |
| exit 1 | |
| fi | |
| echo finished | |
| deploy: | |
| name: 🚀 Publish build assets | |
| runs-on: ubuntu-24.04-arm | |
| if: github.event_name == 'release' || github.ref == 'refs/heads/develop' | |
| needs: [build-gh-docker-publish, release-versions] | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| sparse-checkout: | | |
| package.json | |
| sparse-checkout-cone-mode: false | |
| ref: ${{ github.ref }} | |
| - name: Restore build | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: build-production | |
| path: /tmp/build | |
| - name: Publish assets | |
| env: | |
| AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} | |
| AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | |
| AWS_DEFAULT_REGION: 'us-east-1' | |
| GPG_PASSWORD: ${{ secrets.GPG_PASSWORD }} | |
| run: | | |
| REPO_VERSION=$(node -p "require('./package.json').version") | |
| if [[ '${{ github.event_name }}' = 'release' ]]; then | |
| GIT_TAG="${GITHUB_REF#*tags/}" | |
| ARTIFACT_NAME="${REPO_VERSION}" | |
| else | |
| GIT_TAG="" | |
| ARTIFACT_NAME="${REPO_VERSION}.$GITHUB_SHA" | |
| fi; | |
| ROCKET_DEPLOY_DIR="/tmp/deploy" | |
| FILENAME="$ROCKET_DEPLOY_DIR/rocket.chat-$ARTIFACT_NAME.tgz"; | |
| aws s3 cp s3://rocketchat/sign.key.gpg .github/sign.key.gpg | |
| mkdir -p $ROCKET_DEPLOY_DIR | |
| cp .github/sign.key.gpg /tmp | |
| gpg --yes --batch --passphrase=$GPG_PASSWORD /tmp/sign.key.gpg | |
| gpg --allow-secret-key-import --import /tmp/sign.key | |
| rm /tmp/sign.key | |
| ln -s /tmp/build/Rocket.Chat.tar.gz "$FILENAME" | |
| gpg --armor --detach-sign "$FILENAME" | |
| aws s3 cp $ROCKET_DEPLOY_DIR/ s3://download.rocket.chat/build/ --recursive | |
| docker-image-publish: | |
| name: 🚀 Publish Docker Images (DockerHub) | |
| runs-on: ubuntu-24.04-arm | |
| needs: [deploy, release-versions] | |
| env: | |
| DOCKER_TAG: ${{ needs.release-versions.outputs.gh-docker-tag }} | |
| LOWERCASE_REPOSITORY: ${{ needs.release-versions.outputs.lowercase-repo }} | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| sparse-checkout: | | |
| docker-compose-ci.yml | |
| sparse-checkout-cone-mode: false | |
| ref: ${{ github.ref }} | |
| - name: Login to DockerHub | |
| uses: docker/login-action@v3 | |
| with: | |
| username: ${{ secrets.DOCKER_USER }} | |
| password: ${{ secrets.DOCKER_PASS }} | |
| - name: Login to GitHub Container Registry | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ secrets.CR_USER }} | |
| password: ${{ secrets.CR_PAT }} | |
| - name: Download manifests | |
| if: github.actor != 'dependabot[bot]' && (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop') | |
| uses: actions/download-artifact@v6 | |
| with: | |
| pattern: manifests-* | |
| path: /tmp/manifests | |
| merge-multiple: true | |
| - name: Publish Docker images | |
| run: | | |
| set -euo pipefail | |
| set -o xtrace | |
| shopt -s nullglob | |
| # sudo apt-get update -y | |
| # sudo apt-get install -y skopeo | |
| # 'develop' or 'tag' | |
| DOCKER_TAG=$GITHUB_REF_NAME | |
| declare -a TAGS=() | |
| # tag specific tag version | |
| TAGS+=("$DOCKER_TAG") | |
| if [[ $GITHUB_REF == refs/tags/* ]]; then | |
| RELEASE="${{ needs.release-versions.outputs.release }}" | |
| echo "RELEASE: $RELEASE" | |
| if [[ $RELEASE == 'latest' ]]; then | |
| if [[ '${{ needs.release-versions.outputs.latest-release }}' == $GITHUB_REF_NAME ]]; then | |
| TAGS+=("$RELEASE") | |
| fi | |
| else | |
| TAGS+=("$RELEASE") | |
| fi | |
| fi | |
| # commit hash | |
| COMMIT_SHA="sha-${GITHUB_SHA:0:7}" | |
| echo "COMMIT_SHA: ${COMMIT_SHA}" | |
| TAGS+=("${COMMIT_SHA}") | |
| echo "Tags: ${TAGS[*]}" | |
| # get first tag as primary | |
| PRIMARY="${TAGS[0]}" | |
| for service_dir in /tmp/manifests/*; do | |
| [[ -d "$service_dir" ]] || continue | |
| service="$(basename "$service_dir")" | |
| if [ "$service" == "rocketchat-cov" ]; then | |
| continue | |
| fi | |
| echo "Promoting $service" | |
| if [[ "${service}" == 'rocketchat' ]]; then | |
| IMAGE_NAME="${{ needs.release-versions.outputs.lowercase-repo }}/rocket.chat" | |
| else | |
| IMAGE_NAME="${{ needs.release-versions.outputs.lowercase-repo }}/${service}" | |
| fi | |
| # Get image name from docker-compose-ci.yml since rocketchat image is different from service name (rocket.chat) | |
| SRC=$(docker compose -f docker-compose-ci.yml config --format json 2>/dev/null | jq -r --arg s "${service}" '.services[$s].image') | |
| DEST_REPO="docker.io/${IMAGE_NAME}" | |
| echo "Copying $SRC to ${DEST_REPO}:${PRIMARY}" | |
| skopeo copy --all \ | |
| "docker://${SRC}" \ | |
| "docker://${DEST_REPO}:${PRIMARY}" | |
| # copy additional tags | |
| if (( ${#TAGS[@]} > 1 )); then | |
| for t in "${TAGS[@]:1}"; do | |
| echo "Copying $SRC to ${DEST_REPO}:${t}" | |
| skopeo copy --all \ | |
| "docker://${SRC}" \ | |
| "docker://${DEST_REPO}:${t}" | |
| done | |
| fi | |
| done | |
| notify-services: | |
| name: 🚀 Notify external services | |
| runs-on: ubuntu-24.04-arm | |
| needs: | |
| - docker-image-publish | |
| - release-versions | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| sparse-checkout: | | |
| package.json | |
| sparse-checkout-cone-mode: false | |
| ref: ${{ github.ref }} | |
| - name: Releases service | |
| env: | |
| UPDATE_TOKEN: ${{ secrets.UPDATE_TOKEN }} | |
| run: | | |
| REPO_VERSION=$(node -p "require('./package.json').version") | |
| if [[ '${{ github.event_name }}' = 'release' ]]; then | |
| GIT_TAG="${GITHUB_REF#*tags/}" | |
| GIT_BRANCH="" | |
| ARTIFACT_NAME="${REPO_VERSION}" | |
| RC_VERSION=$GIT_TAG | |
| if [[ '${{ needs.release-versions.outputs.release }}' = 'release-candidate' ]]; then | |
| RC_RELEASE=candidate | |
| elif [[ '${{ needs.release-versions.outputs.release }}' = 'latest' ]]; then | |
| RC_RELEASE=stable | |
| fi | |
| else | |
| GIT_TAG="" | |
| GIT_BRANCH="${GITHUB_REF#*heads/}" | |
| ARTIFACT_NAME="${REPO_VERSION}.$GITHUB_SHA" | |
| RC_VERSION="${REPO_VERSION}" | |
| RC_RELEASE=develop | |
| fi; | |
| curl -H "Content-Type: application/json" -H "X-Update-Token: $UPDATE_TOKEN" -d \ | |
| "{\"nodeVersion\": \"${{ needs.release-versions.outputs.node-version }}\", \"denoVersion\": \"${{ needs.release-versions.outputs.deno-version }}\", \"compatibleMongoVersions\": [\"5\", \"6\", \"7\", \"8\"], \"commit\": \"$GITHUB_SHA\", \"tag\": \"$RC_VERSION\", \"branch\": \"$GIT_BRANCH\", \"artifactName\": \"$ARTIFACT_NAME\", \"releaseType\": \"$RC_RELEASE\"}" \ | |
| https://releases.rocket.chat/update | |
| # Makes build fail if the release isn't there | |
| curl --fail https://releases.rocket.chat/$RC_VERSION/info | |
| docs-update: | |
| name: Update Version Durability | |
| if: github.event_name == 'release' | |
| needs: | |
| - docker-image-publish | |
| uses: ./.github/workflows/update-version-durability.yml | |
| with: | |
| LTS_VERSIONS: ${{ vars.LTS_VERSIONS }} | |
| secrets: | |
| CI_PAT: ${{ secrets.CI_PAT }} | |
| D360_TOKEN: ${{ secrets.D360_TOKEN }} |