Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
Code scanning - action / CodeQL-Build (push) Failing after 2s
247 lines
10 KiB
YAML
247 lines
10 KiB
YAML
name: 'Build Docker'
|
|
description: 'Build Docker images for Rocket.Chat and related services'
|
|
|
|
inputs:
|
|
CR_USER:
|
|
required: true
|
|
description: 'GitHub Container Registry username'
|
|
CR_PAT:
|
|
required: true
|
|
description: 'GitHub Container Registry Personal Access Token'
|
|
DOCKER_USER:
|
|
required: false
|
|
description: 'DockerHub username (required for FIPS builds to pull private base image)'
|
|
DOCKER_PASS:
|
|
required: false
|
|
description: 'DockerHub password (required for FIPS builds to pull private base image)'
|
|
deno-version:
|
|
required: true
|
|
description: 'Deno version'
|
|
arch:
|
|
required: false
|
|
description: 'Architecture'
|
|
default: 'arm64'
|
|
service:
|
|
required: false
|
|
description: 'Container to build'
|
|
publish-image:
|
|
required: false
|
|
description: 'Publish image'
|
|
default: 'true'
|
|
setup-docker:
|
|
required: false
|
|
description: 'Setup Docker'
|
|
default: 'true'
|
|
type:
|
|
required: false
|
|
description: 'production, coverage, or fips'
|
|
default: 'coverage'
|
|
|
|
runs:
|
|
using: composite
|
|
|
|
steps:
|
|
- name: Login to GitHub Container Registry
|
|
if: inputs.publish-image == 'true' && 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@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
|
|
with:
|
|
registry: ghcr.io
|
|
username: ${{ inputs.CR_USER }}
|
|
password: ${{ inputs.CR_PAT }}
|
|
|
|
- name: Login to DockerHub
|
|
# FIPS base image (rocketchat/dhi-node) lives in a private DockerHub repo and requires auth to pull.
|
|
if: inputs.type == 'fips' && (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.event_name == 'merge_group' || github.ref == 'refs/heads/develop')
|
|
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
|
|
with:
|
|
username: ${{ inputs.DOCKER_USER }}
|
|
password: ${{ inputs.DOCKER_PASS }}
|
|
|
|
- name: Restore meteor build
|
|
if: inputs.service == 'rocketchat'
|
|
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
|
|
with:
|
|
name: build-${{ inputs.type == 'fips' && ((github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production') || inputs.type }}
|
|
path: /tmp/build
|
|
|
|
- name: Unpack meteor build
|
|
if: inputs.service == 'rocketchat'
|
|
shell: bash
|
|
run: |
|
|
cd /tmp/build
|
|
tar xzf Rocket.Chat.tar.gz
|
|
rm Rocket.Chat.tar.gz
|
|
|
|
- name: Set up Docker
|
|
if: inputs.setup-docker == 'true'
|
|
uses: docker/setup-docker-action@e43656e248c0bd0647d3f5c195d116aacf6fcaf4 # v4.7.0
|
|
with:
|
|
daemon-config: |
|
|
{
|
|
"debug": false,
|
|
"features": {
|
|
"containerd-snapshotter": true
|
|
}
|
|
}
|
|
|
|
# Microservice images build from a pruned, self-contained context (out/<service>)
|
|
# produced by `turbo prune`, instead of a hand-maintained list of COPY lines.
|
|
# The rocketchat (Meteor) image is a prebuilt bundle and is staged separately above.
|
|
- name: Stage service build context
|
|
if: inputs.service != 'rocketchat'
|
|
shell: bash
|
|
env:
|
|
INPUT_SERVICE: ${{ inputs.service }}
|
|
run: |
|
|
set -o xtrace
|
|
|
|
# The Docker SERVICE arg (folder under ee/apps) lives in the compose build args;
|
|
# the compose service name (INPUT_SERVICE) can differ (e.g. ddp-streamer-service).
|
|
SERVICE_DIR=$(docker compose -f docker-compose-ci.yml config --format json 2>/dev/null | jq -r --arg s "$INPUT_SERVICE" '.services[$s].build.args.SERVICE')
|
|
PKG_NAME=$(node -p "require('./ee/apps/${SERVICE_DIR}/package.json').name")
|
|
TURBO_VERSION=$(node -p "require('./package.json').devDependencies.turbo")
|
|
|
|
rm -rf "out/${SERVICE_DIR}"
|
|
|
|
# `turbo prune` derives the exact workspace dependency closure for the service — no
|
|
# hand-maintained list. --use-gitignore=false also captures the gitignored build output
|
|
# we need (dist/, generated definition/), at the cost of dragging in node_modules/.turbo,
|
|
# which we strip below; `yarn workspaces focus --production` rebuilds node_modules in-image.
|
|
npx -y "turbo@${TURBO_VERSION}" prune "$PKG_NAME" --skip-infer --use-gitignore=false --out-dir "out/${SERVICE_DIR}"
|
|
|
|
find "out/${SERVICE_DIR}" \( -name node_modules -o -name .turbo \) -type d -prune -exec rm -rf {} +
|
|
|
|
- name: Build Docker images
|
|
shell: bash
|
|
env:
|
|
DENO_VERSION: ${{ inputs.deno-version }}
|
|
INPUT_ARCH: ${{ inputs.arch }}
|
|
INPUT_SERVICE: ${{ inputs.service }}
|
|
INPUT_PUBLISH_IMAGE: ${{ inputs.publish-image }}
|
|
INPUT_TYPE: ${{ inputs.type }}
|
|
GITHUB_RUN_ID: ${{ github.run_id }}
|
|
GITHUB_SERVER_URL: ${{ github.server_url }}
|
|
GITHUB_REPOSITORY: ${{ github.repository }}
|
|
GITHUB_EVENT_NAME: ${{ github.event_name }}
|
|
GITHUB_REF: ${{ github.ref }}
|
|
run: |
|
|
set -o xtrace
|
|
compose_fips_override=''
|
|
if [[ "$INPUT_TYPE" == 'fips' ]]; then
|
|
compose_fips_override='-f docker-compose-ci.fips.yml'
|
|
fi
|
|
|
|
# Removes unnecessary swc cores and sharp binaries to reduce image size
|
|
swc_arch='x64'
|
|
if [[ "$INPUT_SERVICE" == 'rocketchat' ]]; then
|
|
if [[ "$INPUT_ARCH" == 'arm64' ]]; then
|
|
swc_arch='arm64'
|
|
fi
|
|
|
|
find /tmp/build/bundle/programs/server/npm/node_modules/@img -type d -name 'sharp-*' -not -name "*-linuxmusl-${swc_arch}" -exec rm -rf {} +
|
|
|
|
find /tmp/build/bundle/programs/server/npm/node_modules/@napi-rs -type d -name 'pinyin-linux-*' -not -name "*-linux-${swc_arch}-*" -exec rm -rf {} +
|
|
|
|
find /tmp/build/bundle/programs/server/npm/node_modules/@esbuild -type d -name 'linux-*' -not -name "*-${swc_arch}" -exec rm -rf {} +
|
|
|
|
find /tmp/build/bundle/programs/server/npm/node_modules/@rocket.chat/apps/node_modules/@esbuild -type d -name 'linux-*' -not -name "*-${swc_arch}" -exec rm -rf {} +
|
|
fi
|
|
|
|
if [[ "$INPUT_PUBLISH_IMAGE" == 'true' ]]; then
|
|
LOAD_OR_PUSH="--push"
|
|
else
|
|
LOAD_OR_PUSH="--load"
|
|
fi
|
|
|
|
# Get image name from docker-compose-ci.yml since rocketchat image is different from service name (rocket.chat)
|
|
IMAGE=$(docker compose -f docker-compose-ci.yml $compose_fips_override config --format json 2>/dev/null | jq -r --arg s "$INPUT_SERVICE" '.services[$s].image')
|
|
|
|
docker buildx bake \
|
|
-f docker-compose-ci.yml $compose_fips_override \
|
|
${LOAD_OR_PUSH} \
|
|
--allow=fs.read=/tmp/build \
|
|
--set "*.tags+=${IMAGE}-gha-run-${GITHUB_RUN_ID}" \
|
|
--set "*.labels.org.opencontainers.image.description=Build run: ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" \
|
|
--set "*.labels.org.opencontainers.image.source=${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}" \
|
|
--set "*.platform=linux/${INPUT_ARCH}" \
|
|
--set *.cache-from=type=gha \
|
|
--set *.cache-to=type=gha,mode=max \
|
|
--provenance=false \
|
|
--sbom=false \
|
|
--metadata-file "/tmp/meta.json" \
|
|
"$INPUT_SERVICE"
|
|
|
|
echo "Contents of /tmp/meta.json:"
|
|
cat /tmp/meta.json
|
|
|
|
if [[ "$INPUT_PUBLISH_IMAGE" == 'true' ]]; then
|
|
SERVICE_SUFFIX=''
|
|
if [[ "$INPUT_SERVICE" == 'rocketchat' && "$INPUT_TYPE" == 'coverage' ]] && [[ "$GITHUB_EVENT_NAME" == 'release' || "$GITHUB_REF" == 'refs/heads/develop' ]]; then
|
|
SERVICE_SUFFIX='-cov'
|
|
elif [[ "$INPUT_TYPE" == 'fips' ]]; then
|
|
SERVICE_SUFFIX='-fips'
|
|
fi
|
|
|
|
mkdir -p "/tmp/manifests/${INPUT_SERVICE}${SERVICE_SUFFIX}/${INPUT_ARCH}"
|
|
|
|
# Get digest and image info
|
|
DIGEST=$(jq -r --arg service "$INPUT_SERVICE" '.[$service].["containerimage.digest"]' "/tmp/meta.json")
|
|
IMAGE_NO_TAG=$(echo "$IMAGE" | sed 's/:.*$//')
|
|
FULL_IMAGE="${IMAGE_NO_TAG}@${DIGEST}"
|
|
|
|
echo "Inspecting image: $FULL_IMAGE"
|
|
|
|
# Inspect the image and save complete manifest with sizes (using -v for verbose)
|
|
docker manifest inspect -v "$FULL_IMAGE" > "/tmp/manifests/${INPUT_SERVICE}${SERVICE_SUFFIX}/${INPUT_ARCH}/manifest.json"
|
|
|
|
echo "Saved manifest to /tmp/manifests/${INPUT_SERVICE}${SERVICE_SUFFIX}/${INPUT_ARCH}/manifest.json"
|
|
cat "/tmp/manifests/${INPUT_SERVICE}${SERVICE_SUFFIX}/${INPUT_ARCH}/manifest.json" | jq '.'
|
|
fi
|
|
|
|
- name: Save Docker image as artifact
|
|
if: inputs.publish-image == 'false' && inputs.arch == 'amd64'
|
|
shell: bash
|
|
env:
|
|
SERVICE: ${{ inputs.service }}
|
|
ARCH: ${{ inputs.arch }}
|
|
TYPE: ${{ inputs.type }}
|
|
run: |
|
|
set -o xtrace
|
|
compose_fips_override=''
|
|
if [[ "$TYPE" == 'fips' ]]; then
|
|
compose_fips_override='-f docker-compose-ci.fips.yml'
|
|
fi
|
|
|
|
# Get image name from docker-compose-ci.yml
|
|
IMAGE=$(docker compose -f docker-compose-ci.yml $compose_fips_override config --format json 2>/dev/null | jq -r --arg s "$SERVICE" '.services[$s].image')
|
|
|
|
# Create directory for image archives
|
|
mkdir -p /tmp/docker-images
|
|
|
|
# Save the image to a tar file
|
|
docker save "${IMAGE}" -o "/tmp/docker-images/${SERVICE}-${ARCH}-${TYPE}.tar"
|
|
|
|
echo "Saved image to /tmp/docker-images/${SERVICE}-${ARCH}-${TYPE}.tar"
|
|
ls -lh /tmp/docker-images/
|
|
|
|
- name: Upload Docker image artifact
|
|
if: inputs.publish-image == 'false' && inputs.arch == 'amd64'
|
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
|
with:
|
|
name: docker-image-${{ inputs.service }}-${{ inputs.arch }}-${{ inputs.type }}
|
|
path: /tmp/docker-images/${{ inputs.service }}-${{ inputs.arch }}-${{ inputs.type }}.tar
|
|
retention-days: 1
|
|
|
|
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
|
if: inputs.publish-image == 'true'
|
|
with:
|
|
name: manifests-${{ inputs.service }}-${{ inputs.arch }}-${{ inputs.type }}
|
|
path: /tmp/manifests
|
|
retention-days: 5
|
|
|
|
- name: Clean up temporary files
|
|
if: inputs.service == 'rocketchat'
|
|
shell: bash
|
|
run: |
|
|
sudo rm -rf /tmp/build
|