diff --git a/.github/actions/build-docker/action.yml b/.github/actions/build-docker/action.yml index 03d8b7e424c43..42f351520668e 100644 --- a/.github/actions/build-docker/action.yml +++ b/.github/actions/build-docker/action.yml @@ -1,14 +1,10 @@ -name: 'Meteor Docker' +name: 'Build Docker' inputs: CR_USER: required: true CR_PAT: required: true - node-version: - required: true - description: 'Node version' - type: string deno-version: required: true description: 'Deno version' @@ -25,13 +21,10 @@ inputs: required: false description: 'Publish image' default: 'true' - setup: - required: false - description: 'Setup node.js' - default: 'true' - NPM_TOKEN: + setup-docker: required: false - description: 'NPM token' + description: 'Setup Docker' + default: true type: required: false description: 'production or coverage' @@ -49,17 +42,6 @@ runs: username: ${{ inputs.CR_USER }} password: ${{ inputs.CR_PAT }} - - 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 . - - name: Restore meteor build if: inputs.service == 'rocketchat' uses: actions/download-artifact@v6 @@ -76,20 +58,17 @@ runs: rm Rocket.Chat.tar.gz - name: Set up Docker + if: inputs.setup-docker == true uses: docker/setup-docker-action@v4 with: daemon-config: | { - "debug": true, + "debug": false, "features": { "containerd-snapshotter": true } } - - uses: docker/setup-buildx-action@v3 - with: - buildkitd-flags: --oci-worker-gc --oci-worker-gc-keepstorage=4000 - - name: Build Docker images shell: bash run: | @@ -122,10 +101,12 @@ runs: echo "Contents of /tmp/meta.json:" cat /tmp/meta.json - mkdir -p /tmp/digests/${{ inputs.service }}${{ inputs.type == 'coverage' && '-cov' || '' }}/${{ inputs.arch }} + SERVICE_SUFFIX=${{ inputs.service == 'rocketchat' && inputs.type == 'coverage' && (github.event_name == 'release' || github.ref == 'refs/heads/develop') && '-cov' || '' }} + + mkdir -p /tmp/digests/${{ inputs.service }}${SERVICE_SUFFIX}/${{ inputs.arch }} DIGEST=$(jq -r '.["${{ inputs.service }}"].["containerimage.digest"]' "/tmp/meta.json") IMAGE_NO_TAG=$(echo "$IMAGE" | sed 's/:.*$//') - echo "${IMAGE_NO_TAG}@${DIGEST}" > "/tmp/digests/${{ inputs.service }}${{ inputs.type == 'coverage' && '-cov' || '' }}/${{ inputs.arch }}/digest.txt" + echo "${IMAGE_NO_TAG}@${DIGEST}" > "/tmp/digests/${{ inputs.service }}${SERVICE_SUFFIX}/${{ inputs.arch }}/digest.txt" - uses: actions/upload-artifact@v4 if: inputs.publish-image == 'true' diff --git a/.github/actions/meteor-build/action.yml b/.github/actions/meteor-build/action.yml index 2c6d965bca462..e9d6758023193 100644 --- a/.github/actions/meteor-build/action.yml +++ b/.github/actions/meteor-build/action.yml @@ -34,9 +34,7 @@ runs: id: cache-build with: path: /tmp/Rocket.Chat.tar.gz - key: ${{ runner.OS }}-rc-build-${{ inputs.source-hash }} - restore-keys: | - ${{ runner.os }}-rc-build- + key: ${{ runner.os }}-${{ runner.arch }}-${{ inputs.type }}-rc-build-${{ inputs.source-hash }} - name: Set Swap Space uses: pierotofy/set-swap-space@master @@ -65,27 +63,27 @@ runs: if: steps.cache-build.outputs.cache-hit != 'true' with: path: ./node_modules/.vite - key: vite-local-cache-${{ runner.OS }}-${{ hashFiles('package.json') }} + key: vite-local-cache-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('package.json') }} restore-keys: | - vite-local-cache-${{ runner.os }}- + vite-local-cache-${{ runner.os }}-${{ runner.arch }}- - name: Cache meteor local uses: actions/cache@v3 if: steps.cache-build.outputs.cache-hit != 'true' with: path: ./apps/meteor/.meteor/local - key: meteor-local-cache-${{ runner.OS }}-${{ hashFiles('apps/meteor/.meteor/versions') }} + key: meteor-local-cache-${{ runner.os }}-${{ runner.arch }}-${{ inputs.type }}-${{ hashFiles('apps/meteor/.meteor/versions') }} restore-keys: | - meteor-local-cache-${{ runner.os }}- + meteor-local-cache-${{ runner.os }}-${{ runner.arch }}-${{ inputs.type }}- - name: Cache meteor uses: actions/cache@v3 if: steps.cache-build.outputs.cache-hit != 'true' with: path: ~/.meteor - key: meteor-cache-${{ runner.OS }}-${{ hashFiles('apps/meteor/.meteor/release') }} + key: meteor-cache-${{ runner.os }}-${{ runner.arch }}-${{ inputs.type }}-${{ hashFiles('apps/meteor/.meteor/release') }} restore-keys: | - meteor-cache-${{ runner.os }}- + meteor-cache-${{ runner.os }}-${{ runner.arch }}-${{ inputs.type }}- - name: Install Meteor shell: bash diff --git a/.github/actions/setup-playwright/action.yml b/.github/actions/setup-playwright/action.yml index a811cf19753bd..4231e139bddb1 100644 --- a/.github/actions/setup-playwright/action.yml +++ b/.github/actions/setup-playwright/action.yml @@ -11,11 +11,10 @@ runs: path: | ~/.cache/ms-playwright # This is the version of Playwright that we are using, if you are willing to upgrade, you should update this. - key: playwright-1.52.0 + key: playwright-${{ runner.os }}-${{ runner.arch }}-1.52.0 - name: Install Playwright shell: bash if: steps.cache-playwright.outputs.cache-hit != 'true' working-directory: . run: npx playwright install --with-deps - \ No newline at end of file diff --git a/.github/workflows/ci-test-e2e.yml b/.github/workflows/ci-test-e2e.yml index b9e8d96e7cf83..5e2349bca92e5 100644 --- a/.github/workflows/ci-test-e2e.yml +++ b/.github/workflows/ci-test-e2e.yml @@ -20,7 +20,7 @@ on: transporter: type: string mongodb-version: - default: "['5.0', '8.2']" + default: "['8.2']" required: false type: string release: @@ -41,6 +41,9 @@ on: type: required: true type: string + coverage: + required: false + type: string db-watcher-disabled: default: 'true' required: false @@ -66,12 +69,16 @@ env: TOOL_NODE_FLAGS: ${{ vars.TOOL_NODE_FLAGS }} LOWERCASE_REPOSITORY: ${{ inputs.lowercase-repo }} DOCKER_TAG: ${{ inputs.gh-docker-tag }} - DOCKER_TAG_SUFFIX_ROCKETCHAT: '-cov' jobs: test: runs-on: ubuntu-24.04 + env: + # if building for production on develop branch or release, add suffix for coverage images + DOCKER_TAG_SUFFIX_ROCKETCHAT: ${{ inputs.coverage == matrix.mongodb-version && (github.event_name == 'release' || github.ref == 'refs/heads/develop') && '-cov' || '' }} + MONGODB_VERSION: ${{ matrix.mongodb-version }} + strategy: fail-fast: false matrix: @@ -105,13 +112,6 @@ jobs: username: ${{ secrets.CR_USER }} password: ${{ secrets.CR_PAT }} - - name: Launch MongoDB - uses: supercharge/mongodb-github-action@1.12.0 - with: - mongodb-image: mongodb/mongodb-community-server - mongodb-version: ${{ matrix.mongodb-version }}-ubi8 - mongodb-replica-set: rs0 - - uses: actions/checkout@v5 - name: Setup NodeJS @@ -142,12 +142,9 @@ jobs: with: CR_USER: ${{ secrets.CR_USER }} CR_PAT: ${{ secrets.CR_PAT }} - node-version: ${{ inputs.node-version }} # the same reason we need to rebuild the docker image at this point is the reason we dont want to publish it publish-image: false - setup: false service: 'rocketchat' - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - name: Set DEBUG_LOG_LEVEL (debug enabled) if: runner.debug == '1' @@ -156,58 +153,34 @@ jobs: - name: Start httpbin container and wait for it to be ready if: inputs.type == 'api' run: | - docker run -d -p 10000:80 --name httpbin-container kennethreitz/httpbin - i=0 - while [ $i -lt 10 ]; do - if curl -s -o /dev/null http://localhost:10000; then - echo "httpbin is running" - break - fi - i=$((i + 1)) - sleep 5 - done - if [ $i -eq 10 ]; then - echo "Failed to verify httpbin is running" - exit 1 - fi + docker compose -f docker-compose-ci.yml up -d httpbin - name: Prepare code coverage directory - if: inputs.release == 'ee' + if: inputs.coverage == matrix.mongodb-version run: | mkdir -p /tmp/coverage chmod 777 /tmp/coverage - name: Start containers for CE if: inputs.release == 'ce' - env: - MONGO_URL: 'mongodb://host.docker.internal:27017/rocketchat?replicaSet=rs0&directConnection=true' run: | # when we are testing CE, we only need to start the rocketchat container - DEBUG_LOG_LEVEL=${DEBUG_LOG_LEVEL:-0} docker compose -f docker-compose-ci.yml up -d rocketchat + DEBUG_LOG_LEVEL=${DEBUG_LOG_LEVEL:-0} docker compose -f docker-compose-ci.yml up -d rocketchat --wait - name: Start containers for EE if: inputs.release == 'ee' env: - MONGO_URL: 'mongodb://host.docker.internal:27017/rocketchat?replicaSet=rs0&directConnection=true' ENTERPRISE_LICENSE: ${{ inputs.enterprise-license }} TRANSPORTER: ${{ inputs.transporter }} COVERAGE_DIR: '/tmp/coverage' COVERAGE_REPORTER: 'lcov' DISABLE_DB_WATCHERS: ${{ inputs.db-watcher-disabled }} run: | - DEBUG_LOG_LEVEL=${DEBUG_LOG_LEVEL:-0} docker compose -f docker-compose-ci.yml up -d + DEBUG_LOG_LEVEL=${DEBUG_LOG_LEVEL:-0} docker compose -f docker-compose-ci.yml up -d --wait - uses: ./.github/actions/setup-playwright if: inputs.type == 'ui' - - name: Wait for Rocket.Chat to start up - uses: cygnetdigital/wait_for_response@v2.0.0 - with: - url: 'http://localhost:3000/health' - responseCode: '200' - timeout: 60000 - interval: 1000 - - name: Wait services to start up if: inputs.release == 'ee' run: | @@ -226,30 +199,15 @@ jobs: if: inputs.type == 'api' working-directory: ./apps/meteor env: - WEBHOOK_TEST_URL: 'http://host.docker.internal:10000' + WEBHOOK_TEST_URL: 'http://httpbin' IS_EE: ${{ inputs.release == 'ee' && 'true' || '' }} COVERAGE_DIR: '/tmp/coverage' COVERAGE_REPORTER: 'lcovonly' run: | - for i in $(seq 1 2); do - npm run testapi && s=0 && break || s=$? - - docker compose -f ../../docker-compose-ci.yml logs --tail=100 - - docker compose -f ../../docker-compose-ci.yml stop + set -o xtrace - docker exec mongodb bash -c 'if command -v mongosh ; then mongosh --eval "use rocketchat" --eval "db.dropDatabase()" rocketchat; else mongo rocketchat --eval "db.dropDatabase()"; fi' + npm run testapi - NOW=$(date "+%Y-%m-%dT%H:%M:%S.000Z") - - docker compose -f ../../docker-compose-ci.yml restart - - until echo "$(docker compose -f ../../docker-compose-ci.yml logs rocketchat --since $NOW)" | grep -q "SERVER RUNNING"; do - echo "Waiting Rocket.Chat to start up" - ((c++)) && ((c==10)) && exit 1 - sleep 10 - done; - done; docker compose -f ../../docker-compose-ci.yml stop ls -l $COVERAGE_DIR @@ -258,7 +216,7 @@ jobs: - name: E2E Test UI (${{ matrix.shard }}/${{ inputs.total-shard }}) if: inputs.type == 'ui' env: - E2E_COVERAGE: ${{ inputs.release == 'ee' && 'true' || '' }} + E2E_COVERAGE: ${{ inputs.coverage == matrix.mongodb-version && 'true' || '' }} IS_EE: ${{ inputs.release == 'ee' && 'true' || '' }} REPORTER_ROCKETCHAT_API_KEY: ${{ secrets.REPORTER_ROCKETCHAT_API_KEY }} REPORTER_ROCKETCHAT_URL: ${{ secrets.REPORTER_ROCKETCHAT_URL }} @@ -289,20 +247,20 @@ jobs: include-hidden-files: true - name: Show server logs if E2E test failed - if: failure() && inputs.release == 'ee' - run: docker compose -f docker-compose-ci.yml logs + if: failure() + run: docker compose -f docker-compose-ci.yml logs rocketchat authorization-service queue-worker-service ddp-streamer-service account-service presence-service stream-hub-service omnichannel-transcript-service - - name: Show server logs if E2E test failed - if: failure() && inputs.release != 'ee' - run: docker compose -f docker-compose-ci.yml logs rocketchat + - name: Show mongo logs if E2E test failed + if: failure() + run: docker compose -f docker-compose-ci.yml logs mongo - name: Extract e2e:ee:coverage - if: inputs.type == 'ui' && inputs.release == 'ee' + if: inputs.coverage == matrix.mongodb-version && inputs.type == 'ui' working-directory: ./apps/meteor run: yarn test:e2e:nyc - uses: codecov/codecov-action@v3 - if: inputs.type == 'ui' && inputs.release == 'ee' + if: inputs.coverage == matrix.mongodb-version && inputs.type == 'ui' with: directory: ./apps/meteor flags: e2e @@ -310,7 +268,7 @@ jobs: token: ${{ secrets.CODECOV_TOKEN }} - uses: codecov/codecov-action@v3 - if: inputs.type == 'api' && inputs.release == 'ee' + if: inputs.coverage == matrix.mongodb-version && inputs.type == 'api' with: directory: /tmp/coverage working-directory: . @@ -319,7 +277,7 @@ jobs: token: ${{ secrets.CODECOV_TOKEN }} - name: Store e2e-api-ee-coverage - if: inputs.type == 'api' && inputs.release == 'ee' + if: inputs.coverage == matrix.mongodb-version && inputs.type == 'api' uses: actions/upload-artifact@v4 with: name: e2e-api-ee-coverage-${{ matrix.mongodb-version }}-${{ matrix.shard }} @@ -327,7 +285,7 @@ jobs: include-hidden-files: true - name: Store e2e-ee-coverage - if: inputs.type == 'ui' && inputs.release == 'ee' + if: inputs.coverage == matrix.mongodb-version && inputs.type == 'ui' uses: actions/upload-artifact@v4 with: name: e2e-ee-coverage-${{ matrix.mongodb-version }}-${{ matrix.shard }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 053cbfcef9136..a10b935cf66d6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,6 @@ jobs: lowercase-repo: ${{ steps.var.outputs.lowercase-repo }} node-version: ${{ steps.var.outputs.node-version }} deno-version: ${{ steps.var.outputs.deno-version }} - services: ${{ steps.var.outputs.services }} 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 @@ -69,6 +68,9 @@ jobs: SOURCE_HASH=$(sha256sum /tmp/RocketChat-source.tar | awk '{ print $1 }')-v3 + # 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 @@ -88,8 +90,6 @@ jobs: echo "DENO_VERSION: ${DENO_VERSION}" echo "deno-version=${DENO_VERSION}" >> $GITHUB_OUTPUT - echo "services=[\"rocketchat\",\"authorization-service\",\"account-service\",\"ddp-streamer-service\",\"presence-service\",\"stream-hub-service\",\"queue-worker-service\",\"omnichannel-transcript-service\"]" >> $GITHUB_OUTPUT - - id: by-tag run: | if echo "$GITHUB_REF_NAME" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$' ; then @@ -173,8 +173,6 @@ jobs: path: | /tmp/RocketChat-packages-build.tar.gz key: ${{ runner.OS }}-packages-build-${{ needs.release-versions.outputs.source-hash }} - restore-keys: | - ${{ runner.os }}-packages-build- - name: Debug cache-hit run: echo "cache-hit=${{ steps.packages-cache-build.outputs.cache-hit }}" @@ -245,7 +243,11 @@ jobs: strategy: fail-fast: false matrix: - type: ['production', 'coverage'] + type: + - production + - coverage + exclude: + - type: ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'production' || '' }} steps: - name: Collect Workflow Telemetry @@ -276,33 +278,97 @@ jobs: strategy: fail-fast: false matrix: - arch: ['amd64', 'arm64'] - service: ${{ fromJson(needs.release-versions.outputs.services) }} - type: ['production'] + 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: - # for rocketchat monolith and on develop branch builds we create a coverage image to run tests against it - # and keep the baseline of the coverage for other PRs + # if not, build with coverage for tests - arch: amd64 - service: rocketchat + service: [rocketchat] + type: coverage + - arch: arm64 + service: [rocketchat] type: coverage steps: - uses: actions/checkout@v5 + - 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 - - uses: ./.github/actions/build-docker + - 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: - DOCKER_TAG_SUFFIX_ROCKETCHAT: ${{ matrix.type == 'coverage' && '-cov' || '' }} + # 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: + # 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[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: + # 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[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: + # 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 }} - node-version: ${{ needs.release-versions.outputs.node-version }} deno-version: ${{ needs.release-versions.outputs.deno-version }} - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} arch: ${{ matrix.arch }} - service: ${{ matrix.service }} + service: ${{ matrix.service[3] }} type: ${{ matrix.type }} + setup-docker: false build-gh-docker-publish: name: 🚢 Publish Docker Images (ghcr.io) @@ -456,7 +522,8 @@ jobs: release: ee transporter: 'nats://nats:4222' enterprise-license: ${{ needs.release-versions.outputs.enterprise-license }} - mongodb-version: "['5.0']" + 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 }} @@ -505,6 +572,7 @@ jobs: 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 }} @@ -617,10 +685,6 @@ jobs: runs-on: ubuntu-24.04 needs: [deploy, release-versions] - strategy: - matrix: - service: ${{ fromJson(needs.release-versions.outputs.services) }} - env: DOCKER_TAG: ${{ needs.release-versions.outputs.gh-docker-tag }} LOWERCASE_REPOSITORY: ${{ needs.release-versions.outputs.lowercase-repo }} @@ -646,32 +710,23 @@ jobs: username: ${{ secrets.CR_USER }} password: ${{ secrets.CR_PAT }} - - name: Get Docker image name - id: gh-docker - run: | - # Get image name from docker-compose-ci.yml since rocketchat image is different from service name (rocket.chat) - GH_IMAGE_NAME=$(docker compose -f docker-compose-ci.yml config --format json 2>/dev/null | jq -r --arg s "${{ matrix.service }}" '.services[$s].image') - - echo "GH_IMAGE_NAME: $GH_IMAGE_NAME" - - echo "gh-image-name=${GH_IMAGE_NAME}" >> $GITHUB_OUTPUT - - - name: Pull Docker image - run: docker pull ${{ steps.gh-docker.outputs.gh-image-name }} + - name: Download digests + 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: digests-* + path: /tmp/digests + 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 - - if [[ '${{ matrix.service }}' == 'rocketchat' ]]; then - IMAGE_NAME="${{ needs.release-versions.outputs.lowercase-repo }}/rocket.chat" - else - IMAGE_NAME="${{ needs.release-versions.outputs.lowercase-repo }}/${{ matrix.service }}" - fi - + # sudo apt-get update -y + # sudo apt-get install -y skopeo + # 'develop' or 'tag' DOCKER_TAG=$GITHUB_REF_NAME @@ -703,24 +758,43 @@ jobs: # get first tag as primary PRIMARY="${TAGS[0]}" + + for service_dir in /tmp/digests/*; do + [[ -d "$service_dir" ]] || continue + service="$(basename "$service_dir")" - SRC="${{ steps.gh-docker.outputs.gh-image-name }}" - 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 + 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 diff --git a/apps/meteor/.docker/Dockerfile.alpine b/apps/meteor/.docker/Dockerfile.alpine index 0576b843f0ce1..72470b2b67772 100644 --- a/apps/meteor/.docker/Dockerfile.alpine +++ b/apps/meteor/.docker/Dockerfile.alpine @@ -18,6 +18,9 @@ ENV LANG=C.UTF-8 # """ RUN apk add --no-cache deno ttf-dejavu \ && apk add --no-cache --virtual deps shadow python3 make g++ py3-setuptools libc6-compat \ + # Update OpenSSL + # CVE -> https://scout.docker.com/vulnerabilities/id/CVE-2025-9230?s=alpine&n=openssl&ns=alpine&t=apk&osn=alpine&osv=3.21 + && apk upgrade --no-cache openssl \ && groupmod -n rocketchat nogroup \ && useradd -u 65533 -r -g rocketchat rocketchat diff --git a/apps/meteor/ee/server/services/Dockerfile b/apps/meteor/ee/server/services/Dockerfile index 1a842005a080d..c3662482d5574 100644 --- a/apps/meteor/ee/server/services/Dockerfile +++ b/apps/meteor/ee/server/services/Dockerfile @@ -1,4 +1,4 @@ -FROM node:22.14.0 as build +FROM node:22.16.0-alpine3.21 as build WORKDIR /app @@ -28,7 +28,7 @@ RUN yarn install RUN yarn workspace @rocket.chat/core-typings run build \ && yarn workspace @rocket.chat/rest-typings run build -FROM node:22.16.0-alpine3.20 +FROM node:22.16.0-alpine3.21 ARG SERVICE @@ -73,6 +73,9 @@ WORKDIR /app/apps/meteor/ee/server/services RUN apk update && \ apk --no-cache --virtual build-dependencies add g++ python3 make py3-setuptools && \ + # Update OpenSSL + # CVE -> https://scout.docker.com/vulnerabilities/id/CVE-2025-9230?s=alpine&n=openssl&ns=alpine&t=apk&osn=alpine&osv=3.21 + apk upgrade --no-cache openssl && \ yarn workspaces focus --production && \ rm -rf /var/cache/apk/* && \ apk del build-dependencies diff --git a/docker-compose-ci.yml b/docker-compose-ci.yml index 75ae6f44672e1..684d28edb5dc5 100644 --- a/docker-compose-ci.yml +++ b/docker-compose-ci.yml @@ -17,9 +17,9 @@ services: - TEST_MODE=true - DEBUG=${DEBUG} - EXIT_UNHANDLEDPROMISEREJECTION=true - - 'MONGO_URL=${MONGO_URL}' - - 'MONGO_OPLOG_URL=${MONGO_OPLOG_URL}' - - 'TRANSPORTER=${TRANSPORTER}' + - MONGO_URL=mongodb://mongo:27017/rocketchat?replicaSet=rs0 + - 'MONGO_OPLOG_URL=${MONGO_OPLOG_URL:-}' + - 'TRANSPORTER=${TRANSPORTER:-}' - MOLECULER_LOG_LEVEL=info - 'ROCKETCHAT_LICENSE=${ENTERPRISE_LICENSE}' - 'COVERAGE_DIR=${COVERAGE_DIR}' @@ -28,16 +28,22 @@ services: - OVERWRITE_SETTING_Log_Level=${DEBUG_LOG_LEVEL:-0} - Federation_Service_Enabled=true - 'Federation_Service_Domain=rc.host' - extra_hosts: - - 'host.docker.internal:host-gateway' + - HEAP_USAGE_PERCENT=99 depends_on: - traefik + - mongo labels: traefik.enable: true traefik.http.services.rocketchat.loadbalancer.server.port: 3000 traefik.http.routers.rocketchat.service: rocketchat traefik.http.routers.rocketchat.rule: PathPrefix(`/`) traefik.http.middlewares.test-retry.retry.attempts: 4 + healthcheck: + interval: 2s + timeout: 5s + retries: 5 + start_period: 60s + test: wget --no-verbose --tries=1 --spider http://127.0.0.1:3000/livez || exit 1 authorization-service: platform: linux/amd64 @@ -50,11 +56,10 @@ services: - linux/arm64 args: SERVICE: authorization-service - DENO_VERSION: ${DENO_VERSION} image: ghcr.io/${LOWERCASE_REPOSITORY}/authorization-service:${DOCKER_TAG} environment: - - 'MONGO_URL=${MONGO_URL}' - - 'TRANSPORTER=${TRANSPORTER}' + - MONGO_URL=mongodb://mongo:27017/rocketchat?replicaSet=rs0 + - 'TRANSPORTER=${TRANSPORTER:-}' - MOLECULER_LOG_LEVEL=info extra_hosts: - 'host.docker.internal:host-gateway' @@ -74,8 +79,8 @@ services: SERVICE: account-service image: ghcr.io/${LOWERCASE_REPOSITORY}/account-service:${DOCKER_TAG} environment: - - MONGO_URL=${MONGO_URL} - - 'TRANSPORTER=${TRANSPORTER}' + - MONGO_URL=mongodb://mongo:27017/rocketchat?replicaSet=rs0 + - 'TRANSPORTER=${TRANSPORTER:-}' - MOLECULER_LOG_LEVEL=info extra_hosts: - 'host.docker.internal:host-gateway' @@ -96,8 +101,8 @@ services: DENO_VERSION: ${DENO_VERSION} image: ghcr.io/${LOWERCASE_REPOSITORY}/presence-service:${DOCKER_TAG} environment: - - MONGO_URL=${MONGO_URL} - - 'TRANSPORTER=${TRANSPORTER}' + - MONGO_URL=mongodb://mongo:27017/rocketchat?replicaSet=rs0 + - 'TRANSPORTER=${TRANSPORTER:-}' - MOLECULER_LOG_LEVEL=info extra_hosts: - 'host.docker.internal:host-gateway' @@ -117,8 +122,8 @@ services: SERVICE: ddp-streamer image: ghcr.io/${LOWERCASE_REPOSITORY}/ddp-streamer-service:${DOCKER_TAG} environment: - - MONGO_URL=${MONGO_URL} - - 'TRANSPORTER=${TRANSPORTER}' + - MONGO_URL=mongodb://mongo:27017/rocketchat?replicaSet=rs0 + - 'TRANSPORTER=${TRANSPORTER:-}' - MOLECULER_LOG_LEVEL=info extra_hosts: - 'host.docker.internal:host-gateway' @@ -144,8 +149,8 @@ services: SERVICE: stream-hub-service image: ghcr.io/${LOWERCASE_REPOSITORY}/stream-hub-service:${DOCKER_TAG} environment: - - MONGO_URL=${MONGO_URL} - - 'TRANSPORTER=${TRANSPORTER}' + - MONGO_URL=mongodb://mongo:27017/rocketchat?replicaSet=rs0 + - 'TRANSPORTER=${TRANSPORTER:-}' - MOLECULER_LOG_LEVEL=info - DISABLE_DB_WATCHERS=${DISABLE_DB_WATCHERS} extra_hosts: @@ -166,8 +171,8 @@ services: SERVICE: queue-worker image: ghcr.io/${LOWERCASE_REPOSITORY}/queue-worker-service:${DOCKER_TAG} environment: - - MONGO_URL=${MONGO_URL} - - 'TRANSPORTER=${TRANSPORTER}' + - MONGO_URL=mongodb://mongo:27017/rocketchat?replicaSet=rs0 + - 'TRANSPORTER=${TRANSPORTER:-}' - MOLECULER_LOG_LEVEL=info extra_hosts: - 'host.docker.internal:host-gateway' @@ -188,8 +193,8 @@ services: image: ghcr.io/${LOWERCASE_REPOSITORY}/omnichannel-transcript-service:${DOCKER_TAG} environment: - TEST_MODE=true - - MONGO_URL=${MONGO_URL} - - 'TRANSPORTER=${TRANSPORTER}' + - MONGO_URL=mongodb://mongo:27017/rocketchat?replicaSet=rs0 + - 'TRANSPORTER=${TRANSPORTER:-}' - MOLECULER_LOG_LEVEL=info extra_hosts: - 'host.docker.internal:host-gateway' @@ -199,6 +204,32 @@ services: nats: image: nats:2.6-alpine + mongo: + image: mongodb/mongodb-community-server:${MONGODB_VERSION:-8.2}-ubi8 + container_name: mongo + restart: on-failure + ports: + - 27017:27017 + environment: + MONGODB_REPLICA_SET_NAME: ${MONGODB_REPLICA_SET_NAME:-rs0} + MONGODB_PORT_NUMBER: ${MONGODB_PORT_NUMBER:-27017} + MONGODB_INITIAL_PRIMARY_HOST: ${MONGODB_INITIAL_PRIMARY_HOST:-mongo} + entrypoint: | + bash -c + "mongod --replSet $$MONGODB_REPLICA_SET_NAME --bind_ip_all & + sleep 2; + until mongosh --eval \"db.adminCommand('ping')\"; do + echo '=====> Waiting for Mongo...'; + sleep 1; + done; + echo \"=====> Initiating ReplSet $$MONGODB_REPLICA_SET_NAME at $$MONGODB_INITIAL_PRIMARY_HOST:$$MONGODB_PORT_NUMBER...\"; + mongosh --eval \"rs.initiate({_id: '$$MONGODB_REPLICA_SET_NAME', members: [{ _id: 0, host: '$$MONGODB_INITIAL_PRIMARY_HOST:$$MONGODB_PORT_NUMBER' }]})\"; + echo '=====> Initiating ReplSet done...'; + wait" + + httpbin: + image: kong/httpbin + traefik: image: traefik:v3.1 command: diff --git a/ee/apps/account-service/Dockerfile b/ee/apps/account-service/Dockerfile index 8b2bcbc783134..bead093d464cb 100644 --- a/ee/apps/account-service/Dockerfile +++ b/ee/apps/account-service/Dockerfile @@ -1,7 +1,10 @@ -FROM node:22.16.0-alpine3.21 +FROM node:22.16.0-alpine3.21 AS builder ARG SERVICE +RUN apk update && \ + apk --no-cache add g++ python3 make py3-setuptools + WORKDIR /app COPY ./packages/core-services/package.json packages/core-services/package.json @@ -80,19 +83,32 @@ COPY ./.yarn/releases .yarn/releases COPY ./.yarn/patches .yarn/patches COPY ./ee/apps/${SERVICE}/package.json ee/apps/${SERVICE}/package.json -ENV NODE_ENV=production \ - PORT=3000 +ENV NODE_ENV=production WORKDIR /app/ee/apps/${SERVICE} +RUN yarn workspaces focus --production + +FROM node:22.16.0-alpine3.21 + +ARG SERVICE + +ENV NODE_ENV=production \ + PORT=3000 + RUN apk update && \ - apk --no-cache --virtual deps add g++ python3 make py3-setuptools shadow && \ - yarn workspaces focus --production && \ + apk --no-cache --virtual deps add shadow && \ + # Update OpenSSL + # CVE -> https://scout.docker.com/vulnerabilities/id/CVE-2025-9230?s=alpine&n=openssl&ns=alpine&t=apk&osn=alpine&osv=3.21 + apk upgrade --no-cache openssl && \ rm -rf /var/cache/apk/* && \ groupmod -n rocketchat nogroup && \ useradd -u 65533 -r -g rocketchat rocketchat && \ - apk del deps && \ - chown -R rocketchat:rocketchat /app + apk del deps + +COPY --chown=rocketchat:rocketchat --from=builder /app /app + +WORKDIR /app/ee/apps/${SERVICE} USER rocketchat diff --git a/ee/apps/authorization-service/Dockerfile b/ee/apps/authorization-service/Dockerfile index ec7dd96967874..ef525715a258e 100644 --- a/ee/apps/authorization-service/Dockerfile +++ b/ee/apps/authorization-service/Dockerfile @@ -1,7 +1,10 @@ -FROM node:22.16.0-alpine3.21 +FROM node:22.16.0-alpine3.21 AS builder ARG SERVICE +RUN apk update && \ + apk --no-cache add g++ python3 make py3-setuptools + WORKDIR /app COPY ./packages/core-services/package.json packages/core-services/package.json @@ -77,19 +80,32 @@ COPY ./.yarn/releases .yarn/releases COPY ./.yarn/patches .yarn/patches COPY ./ee/apps/${SERVICE}/package.json ee/apps/${SERVICE}/package.json -ENV NODE_ENV=production \ - PORT=3000 +ENV NODE_ENV=production WORKDIR /app/ee/apps/${SERVICE} +RUN yarn workspaces focus --production + +FROM node:22.16.0-alpine3.21 + +ARG SERVICE + +ENV NODE_ENV=production \ + PORT=3000 + RUN apk update && \ - apk --no-cache --virtual deps add g++ python3 make py3-setuptools shadow && \ - yarn workspaces focus --production && \ + apk --no-cache --virtual deps add shadow && \ + # Update OpenSSL + # CVE -> https://scout.docker.com/vulnerabilities/id/CVE-2025-9230?s=alpine&n=openssl&ns=alpine&t=apk&osn=alpine&osv=3.21 + apk upgrade --no-cache openssl && \ rm -rf /var/cache/apk/* && \ groupmod -n rocketchat nogroup && \ useradd -u 65533 -r -g rocketchat rocketchat && \ - apk del deps && \ - chown -R rocketchat:rocketchat /app + apk del deps + +COPY --chown=rocketchat:rocketchat --from=builder /app /app + +WORKDIR /app/ee/apps/${SERVICE} USER rocketchat diff --git a/ee/apps/ddp-streamer/Dockerfile b/ee/apps/ddp-streamer/Dockerfile index a0758299c86f5..8ba1e076e7ae6 100644 --- a/ee/apps/ddp-streamer/Dockerfile +++ b/ee/apps/ddp-streamer/Dockerfile @@ -1,7 +1,10 @@ -FROM node:22.16.0-alpine3.21 +FROM node:22.16.0-alpine3.21 AS builder ARG SERVICE +RUN apk update && \ + apk --no-cache add g++ python3 make py3-setuptools + WORKDIR /app COPY ./packages/core-services/package.json packages/core-services/package.json @@ -83,19 +86,32 @@ COPY ./.yarn/releases .yarn/releases COPY ./.yarn/patches .yarn/patches COPY ./ee/apps/${SERVICE}/package.json ee/apps/${SERVICE}/package.json -ENV NODE_ENV=production \ - PORT=3000 +ENV NODE_ENV=production WORKDIR /app/ee/apps/${SERVICE} +RUN yarn workspaces focus --production + +FROM node:22.16.0-alpine3.21 + +ARG SERVICE + +ENV NODE_ENV=production \ + PORT=3000 + RUN apk update && \ - apk --no-cache --virtual deps add g++ python3 make py3-setuptools shadow && \ - yarn workspaces focus --production && \ + apk --no-cache --virtual deps add shadow && \ + # Update OpenSSL + # CVE -> https://scout.docker.com/vulnerabilities/id/CVE-2025-9230?s=alpine&n=openssl&ns=alpine&t=apk&osn=alpine&osv=3.21 + apk upgrade --no-cache openssl && \ rm -rf /var/cache/apk/* && \ groupmod -n rocketchat nogroup && \ useradd -u 65533 -r -g rocketchat rocketchat && \ - apk del deps && \ - chown -R rocketchat:rocketchat /app + apk del deps + +COPY --chown=rocketchat:rocketchat --from=builder /app /app + +WORKDIR /app/ee/apps/${SERVICE} USER rocketchat diff --git a/ee/apps/omnichannel-transcript/Dockerfile b/ee/apps/omnichannel-transcript/Dockerfile index 5b566def3edc2..545809c333787 100644 --- a/ee/apps/omnichannel-transcript/Dockerfile +++ b/ee/apps/omnichannel-transcript/Dockerfile @@ -1,7 +1,10 @@ -FROM node:22.16.0-alpine3.21 +FROM node:22.16.0-alpine3.21 AS builder ARG SERVICE +RUN apk update && \ + apk --no-cache add g++ python3 make py3-setuptools + WORKDIR /app COPY ./packages/core-services/package.json packages/core-services/package.json @@ -93,19 +96,32 @@ COPY ./.yarn/releases .yarn/releases COPY ./.yarn/patches .yarn/patches COPY ./ee/apps/${SERVICE}/package.json ee/apps/${SERVICE}/package.json -ENV NODE_ENV=production \ - PORT=3000 +ENV NODE_ENV=production WORKDIR /app/ee/apps/${SERVICE} +RUN yarn workspaces focus --production + +FROM node:22.16.0-alpine3.21 + +ARG SERVICE + +ENV NODE_ENV=production \ + PORT=3000 + RUN apk update && \ - apk --no-cache --virtual deps add g++ python3 make py3-setuptools shadow && \ - yarn workspaces focus --production && \ + apk --no-cache --virtual deps add shadow && \ + # Update OpenSSL + # CVE -> https://scout.docker.com/vulnerabilities/id/CVE-2025-9230?s=alpine&n=openssl&ns=alpine&t=apk&osn=alpine&osv=3.21 + apk upgrade --no-cache openssl && \ rm -rf /var/cache/apk/* && \ groupmod -n rocketchat nogroup && \ useradd -u 65533 -r -g rocketchat rocketchat && \ - apk del deps && \ - chown -R rocketchat:rocketchat /app + apk del deps + +COPY --chown=rocketchat:rocketchat --from=builder /app /app + +WORKDIR /app/ee/apps/${SERVICE} USER rocketchat diff --git a/ee/apps/presence-service/Dockerfile b/ee/apps/presence-service/Dockerfile index aedd59b187c0e..cc058f195b711 100644 --- a/ee/apps/presence-service/Dockerfile +++ b/ee/apps/presence-service/Dockerfile @@ -1,7 +1,10 @@ -FROM node:22.16.0-alpine3.21 +FROM node:22.16.0-alpine3.21 AS builder ARG SERVICE +RUN apk update && \ + apk --no-cache add g++ python3 make py3-setuptools + WORKDIR /app COPY ./ee/packages/presence/package.json ee/packages/presence/package.json @@ -81,19 +84,32 @@ COPY ./.yarn/releases .yarn/releases COPY ./.yarn/patches .yarn/patches COPY ./ee/apps/${SERVICE}/package.json ee/apps/${SERVICE}/package.json -ENV NODE_ENV=production \ - PORT=3000 +ENV NODE_ENV=production WORKDIR /app/ee/apps/${SERVICE} +RUN yarn workspaces focus --production + +FROM node:22.16.0-alpine3.21 + +ARG SERVICE + +ENV NODE_ENV=production \ + PORT=3000 + RUN apk update && \ - apk --no-cache --virtual deps add g++ python3 make py3-setuptools shadow && \ - yarn workspaces focus --production && \ + apk --no-cache --virtual deps add shadow && \ + # Update OpenSSL + # CVE -> https://scout.docker.com/vulnerabilities/id/CVE-2025-9230?s=alpine&n=openssl&ns=alpine&t=apk&osn=alpine&osv=3.21 + apk upgrade --no-cache openssl && \ rm -rf /var/cache/apk/* && \ groupmod -n rocketchat nogroup && \ useradd -u 65533 -r -g rocketchat rocketchat && \ - apk del deps && \ - chown -R rocketchat:rocketchat /app + apk del deps + +COPY --chown=rocketchat:rocketchat --from=builder /app /app + +WORKDIR /app/ee/apps/${SERVICE} USER rocketchat diff --git a/ee/apps/queue-worker/Dockerfile b/ee/apps/queue-worker/Dockerfile index 5b566def3edc2..545809c333787 100644 --- a/ee/apps/queue-worker/Dockerfile +++ b/ee/apps/queue-worker/Dockerfile @@ -1,7 +1,10 @@ -FROM node:22.16.0-alpine3.21 +FROM node:22.16.0-alpine3.21 AS builder ARG SERVICE +RUN apk update && \ + apk --no-cache add g++ python3 make py3-setuptools + WORKDIR /app COPY ./packages/core-services/package.json packages/core-services/package.json @@ -93,19 +96,32 @@ COPY ./.yarn/releases .yarn/releases COPY ./.yarn/patches .yarn/patches COPY ./ee/apps/${SERVICE}/package.json ee/apps/${SERVICE}/package.json -ENV NODE_ENV=production \ - PORT=3000 +ENV NODE_ENV=production WORKDIR /app/ee/apps/${SERVICE} +RUN yarn workspaces focus --production + +FROM node:22.16.0-alpine3.21 + +ARG SERVICE + +ENV NODE_ENV=production \ + PORT=3000 + RUN apk update && \ - apk --no-cache --virtual deps add g++ python3 make py3-setuptools shadow && \ - yarn workspaces focus --production && \ + apk --no-cache --virtual deps add shadow && \ + # Update OpenSSL + # CVE -> https://scout.docker.com/vulnerabilities/id/CVE-2025-9230?s=alpine&n=openssl&ns=alpine&t=apk&osn=alpine&osv=3.21 + apk upgrade --no-cache openssl && \ rm -rf /var/cache/apk/* && \ groupmod -n rocketchat nogroup && \ useradd -u 65533 -r -g rocketchat rocketchat && \ - apk del deps && \ - chown -R rocketchat:rocketchat /app + apk del deps + +COPY --chown=rocketchat:rocketchat --from=builder /app /app + +WORKDIR /app/ee/apps/${SERVICE} USER rocketchat diff --git a/ee/apps/stream-hub-service/Dockerfile b/ee/apps/stream-hub-service/Dockerfile index 8fc4ab2acce2e..5043c33c44e7e 100644 --- a/ee/apps/stream-hub-service/Dockerfile +++ b/ee/apps/stream-hub-service/Dockerfile @@ -1,7 +1,10 @@ -FROM node:22.16.0-alpine3.21 +FROM node:22.16.0-alpine3.21 AS builder ARG SERVICE +RUN apk update && \ + apk --no-cache add g++ python3 make py3-setuptools + WORKDIR /app COPY ./packages/core-services/package.json packages/core-services/package.json @@ -78,19 +81,32 @@ COPY ./.yarn/releases .yarn/releases COPY ./.yarn/patches .yarn/patches COPY ./ee/apps/${SERVICE}/package.json ee/apps/${SERVICE}/package.json -ENV NODE_ENV=production \ - PORT=3000 +ENV NODE_ENV=production WORKDIR /app/ee/apps/${SERVICE} +RUN yarn workspaces focus --production + +FROM node:22.16.0-alpine3.21 + +ARG SERVICE + +ENV NODE_ENV=production \ + PORT=3000 + RUN apk update && \ - apk --no-cache --virtual deps add g++ python3 make py3-setuptools shadow && \ - yarn workspaces focus --production && \ + apk --no-cache --virtual deps add shadow && \ + # Update OpenSSL + # CVE -> https://scout.docker.com/vulnerabilities/id/CVE-2025-9230?s=alpine&n=openssl&ns=alpine&t=apk&osn=alpine&osv=3.21 + apk upgrade --no-cache openssl && \ rm -rf /var/cache/apk/* && \ groupmod -n rocketchat nogroup && \ useradd -u 65533 -r -g rocketchat rocketchat && \ - apk del deps && \ - chown -R rocketchat:rocketchat /app + apk del deps + +COPY --chown=rocketchat:rocketchat --from=builder /app /app + +WORKDIR /app/ee/apps/${SERVICE} USER rocketchat diff --git a/turbo.json b/turbo.json index d0d7b22aca623..edf2a61d708a2 100644 --- a/turbo.json +++ b/turbo.json @@ -14,7 +14,6 @@ "outputs": ["dist/**"] }, "test-storybook": { - "dependsOn": ["build"], "outputs": ["coverage/**"] }, "testunit": {